工程中最常用git命令

本文力图涵盖常用的git命令,并介绍它们的应用场景,更好地理解git的使用。

关于git的基本概念在这里不做赘述,默认你已经了解这些概念:工作区/暂存区/仓库,远程仓库,HEAD。

本文主要分为6个部分,前5个是你可能最需要的5大功能,第6部分是一个典型第团队协作流程:

  1. 基本配置:git的环境变量(config);
  2. 本地仓库:git项目的开端(clone,init);
  3. 远程仓库:远程仓库和本地仓库交互(remote, fetch,  pull, push, .gitignore, submodule);
  4. 从工作区到仓库:编辑,修改,保存,提交到本地仓库,working->staging->repo链路(status,branch,add,commit,merge,rebase, rm, stash);
  5. 版本控制:版本比较,回退,体现VCS系统本质的强大功能(diff,reset,log,tag);
  6. 典型团队协作流程。

 

  • 基本配置——git的环境变量config

Git congfig 配置

应用场景:一般第一次使用git的时候配置的,类似于配置系统环境变量。--global参数表示全局变量,不加则表示只对本工程有效。Git 为你的每一个提交都记录你的名字与电子邮箱地址,所以第一步需要配置用户名和邮箱地址。

git config --global user.name  "starxhong"

git config --global user.email "starxhong@gmail.com”

 

  • 本地仓库——远程clone或者本地init

git clone 从远端仓库克隆

应用场景:已有一个远程仓库(比如github上别人的远程仓库),你想在此基础上开发。

git clone $url  默认把远程仓库整个clone下来(包括所有分支和历史版本),创建一个对应对本地仓库,在本地默认创建一个master分支,且自动添加远端主机到当前目录,默认主机名为origin(不需要显式地git remote add $hostname $hostaddress创建)

ps: clone默认在本地创建master分支,并与远程master分支关联,但是如果想在本地创建与远程对应的其他分支,直接git checkout origin/$branch_name就好 (如果没记错,2.0之前的git版本,需要用git checkout -b $branch_name  origin/$branch_name)。

# clone远程仓库并以此为基础修改,然后再提交回去
git clone http://git.code.oa.com/group/myproject.git
cd myproject
touch README.md
git add README.md # 添加修改内容到暂存区
git commit -m "add README" # 提交到本地仓库
git pull # 保持良好习惯,push前先pull
git push # 推送到远程主机

 

git init 在本地初始化一个仓库

应用场景:自己开发一个全新项目,所以没有可以clone的远程仓库;或者你download一个远程仓库项目而不是git clone,需要自己本地显式创建仓库,记得还要把工程文件提交到仓库才算完事儿(进一步你可能会把本地仓库push到一个远程仓库上去)

git init 进入你要创建仓库的工作目录执行git init,将创建一个名为 .git 的子目录,包含一些初始化文件。工作目录到文件加入仓库前,需要用git add $filename将其加入暂存区,再用git commit -m ‘some tags‘ 将暂存区内容提交到仓库。

cd existing_folder
git init 
git remote add origin http://git.code.oa.com/group/myproject.git # 添加远程主机
git add . # 将existing_folder文件夹中所有文件存入暂存区
git commit # 提交到本地仓库
git push -u origin master # 推送到远程仓库,因为现在远程仓库啥也没有,所以这里没有pull

 

  • 远程仓库——添加,查看,拉取fech,合并merge,拉取并合并pull,推送push

git remote 远程主机

应用场景:你需要查看或者添加关联远程仓库的时候。

git remote 显示远程主机名,clone下来的项目默认主机名为origin

git remote -v 显示远程主机fetch和push地址

git remote show $hostname 显示远程主机信息,hostname一般是origin

git remote add $hostname $url  添加一个远端主机。如果是git clone下来的项目,默认已经有一个名为origin的远程主机。

 

git fetch  从远程仓库拉取到本地

应用场景:比如你clone了一个远程仓库,吭哧吭哧地开发,同时你同事将他的修改推送到远程仓库,你想把这个更新同步到你本地,你就可以fetch过来。根据需要,你可以fetch全部或者指定分支。但fetch只是下载,不会主动合并到本地。默认fetch所有分支,如果只想取回特定分支的更新,可以指定分支名fetch后一般会merge,才会把远程的修改同步到本地,强烈建议先跳到下一节看看merge命令。

git fetch $hostname  将远程主机的所有分支拉取回本地,可以简写为git fetch。 

git fetch origin master 取回origin主机上master 分支,所取回的更新,在本地主机上要用表示为origin/master,注意跟本地master分支不同。

git checkout -b $branch_name  origin/$branch_name 本地新建与远程分支关联的分支

 

git pull  远程拉取分支并合并到本地分支

应用场景:基本等于fetch + merge,要注意,push你的修改到远程主机前务必先pull,否则你可能覆盖掉你同事辛辛苦苦修改并同步到远程仓库到内容。ps:pull是分支级别

git pull origin master:esMerge 从名为origin的远程仓库拉取master分支,合并到本地esMerge分支上

git pull origin master 从名为origin的远程仓库拉取master分支,合并到当前分支(等于git fetch origin + git merge origin/maseter)

git pull 如果已经指定了远程主机,且远程有一个与当前分支关联的分支,则可直接git pull

 

git push 推送本地分支到远程主机

应用场景:你修改了一些东西,而且已经提交到本地仓库,然后你想把它们推送到远程仓库。push你的修改到远程主机前务必先pull,否则你可能把远端别人提交的代码给覆盖掉。

git push <远程主机名> <本地分支名>:<远程分支名>

git push origin master 本地的master分支推送到origin主机的master分支(命令中远程分支名省略)

git push origin master: new_branch 本地的master分支推送到origin主机,创建一个新的分支new_branch

git push origin 当前分支推送到origin主机的对应分支(前提,当前分支与远程分支之间存在追踪关系)

git push 当前分支只有一个追踪分支,主机名也可以省略

git push origin :master = git push origin --delete master 如果省略本地分支名,表示删除指定远程分支,等同于推送一个空的本地分支到远程分支

git push -u origin master 当前分支与多个主机存在追踪关系,-u指定默认主机,后面就可以不加任何参数使用git push

push配置:

git config --global push.default simple (默认)只push当前分支

git config --global push.default matching  会push所有远程分支匹配上的本地分支

 

git push -all origin 本地所有分支推送到远程,如果远程没有对应的分支,新建之

git push origin —tags 默认git push不会推送标签(tag),除非使用–tags选项

git push origin HEAD 当前分支推送到远程的同名的简单方法

git push origin HEAD:master 当前分支推送到远程的指定分支

 

.gitigonre 忽略文件

应用场景:有些文件,比如用Intellij IDEA作为IDE时,会有一个记录工程信息的.idea文件夹,其下的workspace.xml会自动记录本地工作区实时状态信息,我们并不需要提交到staging层,我们可以将这个文件夹加入.gitignore文件,然后再git add .

还有一种情况是checkout到别的分支时,这个.idea文件自己改变了,报错Error:The following untracked working tree files would be overwritten by checkout:.idea/workspace.xml,我们有两种做法,一种是用git stash命令将当前工作区修改缓存起来,同时工作区回到原始状态,再去checkout;或者就是添加.idea到.gitignore文件。如下:

touch .gitignore #在当前工作区创建.gitignore文件
vim .gitigonre

# 以下为.gitignore文件内容编辑
.idea
# :wq保存后退出编辑

git add .gitignore # 不要忘了 添加.gitignore文件到git中

git submodule 子模块

应用场景:多个工程都用到某个通用的部分,可以抽取出来做成一个公共库来提供给别的工程来使用。同时,这个公共部分也会有更新的需求,比如把通信协议相关代码独立出来作为几个项目的子模块,协议修改后,其他几个项目只需要拉取最新的就好。

具体使用情形可以参考我的另一篇博客:[git submodule使用方法](https://blog.youkuaiyun.com/hongxingabc/article/details/104930042)

 

  • 从工作区到仓库——status/ branch/ checkout/ add/ commit

git status 显示工作目录和暂存区的状态

应用场景:你想知道相对于本地git仓库,你的工作区哪些文件被修改了,哪些已经添加到暂存区,哪些可以被提交到仓库。关注两个指标,一个是“Changes not staged for commit” 表示工作区修改了还没有stage到暂存区,另一个“Changes to be committed”表示工作区修改且stage到暂存,可以被提交到仓库了。

 

git branch 分支显示/创建/删除/远程关联

应用场景:分支相关操作,显示、新建、与远程关联等等。

git branch 显示所有本地branch,等于git branch --list

git branch --list 显示所有本地branch

git branch -r 显示所有远程branch

git branch -a 显示所有branch及细节,红色是remote branch

git branch -vv 显示本地分支和远程分支的关联情况

git branch --merged/--no-merged 显示哪些分支已被(或未被)并入当前分支

git branch --contains 显示当前分支包含哪些子分支

git branch $branch_name 在当前分支(假设为master)下创建新分支 = git checkout -b branch_name

git branch --set-upstream-to=origin/TopItem TopItem 本地新建一个分支后,必须要做远程分支关联,git clone的时候所有本地分支默认与远程主机的同名分支,这里是将本地TopItem分支关联到远程origin/TopItem上

git branch --unset-upstream 取消远程分支关联

git branch -d esCtr 删除本地分支esCtr

git branch -d -r origin/esCtr 删除远程分支esCtr

 

git checkout 分支切换——HEAD是灵魂

应用场景:切换分支。

git checkout $branch_name 切换到branch_name分支

git checkout -b branch_name 在当前分支下创建一个新的branch并切换到该分支

git checkout -b branch_name develop 在develop分支下创建一个新的branch并切换到该分支

有时候,我们checkout失败,主要是因为当前修改没有被保存,可能会丢失。这时你有两种选择,一种是git commit把修改提交,另一种是git stash把当前修改缓存起来,之后要用的时候可以stash pop出来,也可以丢弃掉(就是不pop)。

 

git add 将修改添加到索引

应用场景:你在工作区新建或者修改了内容,将它们添加到暂存区(stage)。注意add前后git status的变化。

git add . 将所有修改添加到暂存区(不建议用)

git add $filename 将某个文件添加到暂存区(建议用)

 

git commit 将暂存区内容提交到本地仓库

应用场景:你已经把修改add到了暂存区,可能add了很多次,你觉得是时候阶段性地把最近的修改做一个总结,提交给repo,这时你就会commit,仓库会生成一个节点(或者说版本),对应一个commit_id。

git commit -m “some massges” 提交暂存区的内容,其要有相关说明。

git commit --amend 追加提交,在不改变commit_id的条件下修改上次提交的内容,相当于一个补丁。注意:amend其实是把上次commit的内容和你要追加的内容一起,覆盖掉上次commit,覆盖包括上次commit的-m说明。

 

git merge 合并一个或多个分支到当前分支

应用场景:merge常和fetch一起使用,但它并不涉及与远程仓库直接联系。比如你fetch了远程仓库的分支,然后用git merge将远程分支合并到当前本地分支,merge做的只是并已经下载到本地的远程分支合并到本地分支,与远程仓库联系是由fetch做的,merge是一个“纯本地操作”。远程仓库的分支!=本地仓库的远程分支,有人觉得git merge origin/master合并了远程的master分支到当前本地分支,就等于和远程仓库到master分支保持同步了,其实不然,比如你3天前fetch,今天merge,但最近3天远程仓库可能被别人改了,那就不是真正同步了,实际一般是fetch后立马merge,或者用它们的结合版pull命令,举这个例子只是为了厘清概念。如果远程分支比本地分支新,建议用fetch + rebase而不是fetch+ merge,或者用git pull --rebase。

git merge b1 b2 把b1和b2两个分支合并到当前分支

git merge origin/master 把拉取到本地的远程分支origin/master合并到当前分支

git merge --abort 合并遇到冲突时,恢复合并前的状态(当合并时存在未commit的文件,git merge --abort将无法恢复,建议先commit再执行merge,或者使用git stash将未commit文件暂存,在解决冲突以后使用git stash pop把未commit文件还原出来)

git merge根据合并分支方式不同,有很多不同参数:--commit/--no-commit,--ff/--no-ff,--log/--no-log,--squash/--no-squash,--stat/--no-stat,…… 具体可以了解:https://www.jianshu.com/p/58a166f24c81

 

git rebase 保持分支更简洁的合并,强烈推荐

应用场景:你想多个commit节点合并为一个节点,比如你从主干分出来一个feature分支,时不时commit一次,推送到远端前,你commit节点太多不太好看,你可以先rebase压缩后再push。但要注意永远不在在一个公共的分支中使用rebase. (如果不知道最近有几次commit,可以用git log看看)

另一个应用场景是,你的feature分支在master基础上,后来远端master被人更新为master1了,如果你直接fetch+merge或者pull下来合并,你将得到新的节点,父节点是master1和feature两个节点。双节点不是太好的结构,你可以fetch下来后用rebase,这样做就是把feature之前的提交回撤到暂存,然后master升级到master1,再把回撤的feature特性加到master1上,相当于直接从master1基础上新建了分支feature,更干净易读。

git rebase -i HEAD~3 合并最近三次commit节点,这里HEAD~n也可以换成commit_id

git rebase origin/master 将新fetch下来的origin/master合并到当前分支,如果把这个rebase换成merge,则是把当前分支和origin/master自动生成一个commit,有两个parents,导致review比较麻烦。

 

git stash 修改缓存

应用场景:你的工作区修改了一堆东西还没有add,或者你add了一堆东西但还不想commit,临时需要切换分支或干其他事情,你可以把修改stash起来(如果当前工作区域文件有修改,要么你commit,要么你stash,否则无法checkout到其他分支),仓库恢复到上次提交状态(这时git diff会发现没有任何改动,因为改动都被stash了)。stash是不区分分支的,这样有个神奇的好处,比如代码写一半,发现忘记切换分支了,你可以stash+checkout把暂存修改“移交”你需要的分支。或者你只是简单地想放弃掉最近的修改,你可以stash后drop掉。

git  stash 当前未提交的修改暂存起来,让仓库还原到最后一次提交的状态

git stash pop 将stash的内容弹出,默认弹出最上面的那条

git stash list 列出当前仓库下所有的stash条目

git stash drop [stash@{n}] 丢弃stash条目,默认丢弃最上面的那条,stash@{0

git stash clear  清除所有的stash条目

 

git rm 和 git rm --cached 删除文件/删除缓存

应用场景:有些本地文件不是远程仓库必须的(比如本地编译器的日志文件),这些文件的修改妨碍了我们提交,可以再暂存区中删除。甚至直接在工作区删除。
git rm file_path 删除暂存区&&工作区
git rm --cached file_path 删除暂存区,但保留工作区

 

  • 版本控制—— diff/ rm/ tag/ reset

git log 历史日志

应用场景:你想知道最近几次commit的时间,commit_id,作者信息。

 

git diff 版本比较

应用场景:版本比较,这里比较涉及同一分支工作区/暂存区和仓库的文件纵向比较,还可以是两个分支之间的横向比较。注意,git diff只能比较tracked file,对于新增但没有关联的file,是无法显示的。可以用git status查看是否有untracked file。

git diff (工作区vs暂存区)

git diff --cached (暂存区vs仓库)

git diff head (工作区vs仓库)

git diff --stat  加--stat参数则显示diff摘要而不是逐行显示

git diff <branch1> <branch2>  在两个分支之间比较,例如git diff origin/master master

 

git tag/show 标签和详情

应用场景:你每次commit都会自动生成一个commit_id,但是这是一个SHA编码你肯定记不住,所以需要一个更人性的id,tag就是这样一个id,比如v1.0.2版本可以打上版本号作为tag名,同时附上“修复了部分bug”作为tag说明。

git tag $name 打一个标签

git tag -a tagName -m “mark” 创建带说明的标签 如git tag -a v1.4.3 -m “fix some bugs, and add a button" 

git tag $name $commit_id 给commit_id打一个标签

git tag -a v0.1 -m "version 1.0" 88d434eb9992fa7502ec246ecfb89aef19f16873 

git tag 列出所有标签,按字母顺序排序

git show $name 显示标签name对应版本信息

git push origin $tag_name 单独将tag push到远程

git push --tags 将所有tag push到远程(不推荐)

 

git reset 重置

应用场景:你从远端拉取了一个分支,改了一顿发现改乱了,需要重新从远程拉取并且重置到本地;或者你从远程pull下来的与本地发生冲突,但是pull命令已经修改了本地,你想重置回pull之前的样子

git reset --soft commit_id 撤回commit到commit_id对应版本,HEAD到commit_id之间所有版本到修改都会撤回到暂存区,工作区保持不变(修改版本库,保留暂存区,保留工作区)

git reset --soft HEAD^ 撤回上一次commit,撤回前n次commit用HEAD~n

git reset --hard  commit-id 版本回退到commit_id,HEAD到commit_id之间所有修改都会被删除,工作区也会恢复到commit_id版本对应到样子(修改版本库,修改暂存区,修改工作区)

git reset --hard HEAD~n 回退n个版本,如n=3,则会永久删除HEAD,HEAD^,HEAD~2这3个最近的修改

git fetch 

git reset --hard origin/master 将当前分支重置为远程分支(舍弃所有与远程分支不同的修改)

git reset Head $file_name 将file_name从暂存区移出

 

典型团队协作流程:

1,fork项目主工程到自己工程中(自己的可以随便折腾,不影响主工程);

2,从自己的远程仓库git clone到本地;

3,git remote add upstream <url> 将项目主工程添加为名为upstream的远程仓库(已有origin指向自己的远程仓库)

4,git fetch upstream 从项目主工程拉取最新的代码(主工程的更新fetch到本地)

5,git merge upstream/master 把主工程更新合并到本地

6,本地修改和提交本地仓库( git add , commit )

7,  git push 本地修改提交到自己远程仓库

8,到自己到远程工程上提交Merge Request,如果code review通过后修改就merge到项目主工程了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值