Git 是目前最流行的版本管理系统,学会 Git 几乎成了开发者的必备技能。Git 有很多优势,其中之一就是远程操作非常简便。本文从初学者的角度出发,对需要用到的Git 命令按用到的顺序进行了一一列举。 目录如下:
- 克隆版本库
- 远程仓库
- 分支的查看、创建、切换
- 分支的删除
- 远程分支的拉取及合并
- 代码的提交
- 未提交代码的撤销、修改
- 已提交代码的回退
- 已 push 代码的回退
- 想要合并其他分支的某个或多个 commit
- 未提交代码暂存
- 标签
一、克隆版本库
远程操作的第一步,通常是从远程主机克隆一个版本库,这时就要用到 git clone
命令。
$ git clone <版本库的网址>
该命令会在本地主机生成一个目录,与远程主机的版本库同名。如果要指定不同的目录名,可以将目录名作为git clone
命令的第二个参数。
$ git clone <版本库的网址> <本地目录名>
git clone
支持多种协议,除了 HTTP(s) 以外,还支持 SSH、Git、本地文件协议等,下面是一些例子。
$ git clone http[s]://example.com/path/to/repo.git/
$ git clone ssh://example.com/path/to/repo.git/
$ git clone git://example.com/path/to/repo.git/
$ git clone /opt/git/project.git
$ git clone file:///opt/git/project.git
$ git clone ftp[s]://example.com/path/to/repo.git/
$ git clone rsync://example.com/path/to/repo.git/
SSH 协议还有另一种写法。
$ git clone [user@]example.com:path/to/repo.git/
克隆版本库的时候,所使用的远程主机自动被 Git 命名为 origin。如果想用其他的主机名,需要用 git clone
命令的 -o 选项指定。
$ git clone -o ABCDE
https://github.com/ABCDE/projectName.git
$ git remote
ABCDE
上面命令表示,克隆的时候,指定远程主机叫做 ABCDE。
二、远程仓库
要查看当前配置有哪些远程仓库,可以用 git remote
命令,它会列出每个远程库的简短名字。在克隆完某个项目后,至少可以看到一个名为 origin 的远程库,Git 默认使用这个名字来标识你所克隆的原始仓库。若想列出详细信息,在每一个远程仓库的名字后面列出其远程 url,可使用参数 -v。
$ git remote -v
origin git@github.com:UserName/ProjectName.git (fetch)
origin git@github.com:UserName/ProjectName.git (push)
想查看远程主机 origin 的详细信息时,使用如下命令:
$ git remote show origin
* remote origin
Fetch URL: git@github.com:UserName/ProjectName.git
Push URL: git@github.com:UserName/ProjectName.git
HEAD branch: master
Remote branches:
branch tracked
master tracked
Local branch configured for 'git pull':
master merges with remote master
Local refs configured for 'git push':
branch pushes to branch (up to date)
master pushes to master (up to date)
想添加远程主机时,使用如下命令:
$ git remote add <主机名> <网址>
想删除远程主机时,使用如下命令:
$ git remote rm <主机名>
rename命令可对远程主机进行改名,
$ git remote rename <原主机名> <新主机名>
三、分支的查看、创建、切换
列出本地已经存在的分支,并且在当前分支的前面加“*”号标记。
$ git branch
查看远程分支,使用参数 -r。
$ git branch -r
查看本地所有分支,还本地分支和远程分支,使用参数 -a。
$ git branch -a
创建一个新的本地分支
$ git branch <分支名>
需要注意,此处只是创建分支,不进行分支切换。若要创建一个新的本地分支并进行分支切换,使用如下命令,
$ git checkout -b <分支名>
切换分支
$ git checkout <分支名>
四、分支的删除
删除某一本地分支,可用 git branch
命令加参数 -D 及对应分支名。
$ git branch -D <分支名>
删除远程分支
$ git push <远程主机名> :<远程分支名>
移除在远程仓库已被删除的远程分支,
$ git remote prune origin
下面的命令也可达到同样的效果。
$ git fetch -p
五、远程分支的拉取及合并
如果要拉取某个远程仓库的分支到本地,并建立追踪(tracking)关系,且拉取后自动切换到该分支上,可使用 git checkout
命令加参数 -t,
$ git checkout -t <远程主机名>/<分支名>
git fetch
取回所有分支(branch)的更新。如果只想取回特定分支的更新,可以指定分支名。
$ git fetch <远程主机名> <分支名>
所取回的更新,在本地主机上要用”远程主机名/分支名”的形式读取,比如 origin 主机的master,就要用 origin/master 读取。
分支合并 git pul
l 命令的作用是,取回远程主机某个分支的更新,再与本地的指定分支合并。
$ git pull <远程主机名> <远程分支名>:<本地分支名>
如果远程分支是与当前分支合并,则冒号后面的部分可以省略。
$ git pull <远程主机名> <远程分支名>
如果略去远程主机名,则默认远程主机名为“orgin”。如果当前分支与远程分支存在追踪关系,连分支名都可以略去。还是,略去远程分支名,会默认把“远程主机名/分支名”合并到“分支名”去。
$ git pull
git merge
的基本用法为把一个分支合并到现在的分支上。git pull
其实就是相当于执行 git fetch
后再执行 git merge
。
$ git merge <分支名>
git merge
带上 -no-ff 参数时,表示哪怕被合并分支处于当前分支的上游,也不使用 fastforward 模式(fastforward表示简单移动指针),而是生成新的 commit,并附有默认的 commit message “Merge branch ‘origin/<分支名>’”。建议使用 -no-ff 模式,这样可以保留被合并分支提交历史的完整性。
git merge
是把某个分支的代码合并到当前分支上,形成一个新的提交,而 git rebase
则是将当前分支的修改添加到某个分支上,形成新的一系列提交,使得当前分支处于被合并分支的上游。
$ git rebase <分支名>
注意,使用 git rebase
,可使得被合并分支的提交历史更加整洁,并保持在一条直线上,但当前分支的每一次待合并的提交都可能与被合并分支产生冲突,可能需要解决多次冲突,git merge
则没有这个问题,最多只需要解决一次冲突。
六、代码的提交
对代码进行改动后,可使用 add 命令将修改的代码放入 index 区域。如果想将当前目录下的所有修改加入到 index 区域,可使用如下命令。
$ git add .
也可单独将某一文件加入到 index 区域。
$ git add <文件名>
如果想对文件上的修改进行部分添加,可使用 -p 参数。
$ git add -p <文件名>
将文件名替换成路径,可一次性添加某一路径下的所有修改。
$ git add <路径>
将 index 区域的所有修改提交到版本库,可使用如下命令提交代码。
$ git commit -m “commit messages”
若使用 -a 参数,则无需使用 git add
命令,会将所有修改全部提交。
git push
命令用于将本地分支的更新,推送到远程主机,它的格式如下。
$ git push <远程主机名> <本地分支名>:<远程分支名>
如果当前分支与远程分支之间存在追踪关系,则本地分支和远程分支都可以省略。
$ git push <远程主机名>
如果是需要创建同名的远程分支,可使用 -u 选项,以后就会自动建立对应的追踪关系,不需要再指明推送到哪个远程仓库的哪个分支上去了。
$ git push -u <远程主机名> <分支名>
还有一种情况,就是不管是否存在对应的远程分支,将本地的所有分支都推送到远程主机,这时需要使用 --all 选项。
$ git push --all <远程主机名>
七、未提交代码的撤销、修改
当你的修改还没提交到远程的中央仓库,且还没有加入了 index 区域时,可使用 git checkout
来回滚代码。
$ git checkout <file1> <file2> … <fileN>
或者可以直接回滚当前目录下的所有修改。
$ git checkout .
若当前修改已加入到 index 区域,则可使用以下命令将当前目录下的所有修改移出 index 区域。
$ git reset .
到这一步之后,使用上面提到 git checkout
就可以解决问题了。
修改已提交后,如果想对最后一次提交进行补救,可使用下面的命令。此时,index 区域的文件会被补充到最后一次提交上去,并且可以修改最后一次提交的 message。
$ git commit --amend
八、已提交代码的回退
如果想恢复到之前的 commit 作为一个新的 commit。
$ git revert <commit>
恢复到三个提交之前的代码状态,使用如下命令,其中数字 3 省略时默认为 1。
$ git revert HEAD~3
git revert
是用一次新的 commit 来回滚之前的 commit,git reset
是直接删除指定的 commit。譬如,撤销之前的 2 个提交,同样 2 可省略,默认为 1。
$ git reset HEAD~2
如果 git reset
带上 soft 参数,表示只回退 commit 信息,保留修改内容到 index 暂存区,若带上 --hard 参数,则表示抛弃修改,彻底回退至某个版本。如:
$ git reset --hard HEAD~
九、已 push 代码的回退
当代码已被 push 到远程服务器时,可先按方法八把本地分支的代码撤回,对于非默认的分支(非 master 分支),可先在远程服务器删除该分支,再把本地分支重新推上去。
$ git push <远程主机名> :<分支名>
$ git push -u <远程主机名> <分支名>
对于 master 分支,无法直接删除远程分支,可使用强推的方法,即利用强覆盖方式用你本地的代码替代 Git 仓库内的内容。
$ git checkout master
$ git push -f
删除远程分支需万分谨慎,要提前做好备份,并知会团队其他成员,确保没有其他成员有关于该分支的未提交、push 的修改。
十、想要合并其他分支的某个或多个 commit
Git 裡有個 cherry-pick
指令,可以只捡某些 Commit 來用,例如想撿 Hash 值为 6c7f86a 的 Commit,如下执行命令即可。
$ git cherry-pick 6c7f86a
cherry-pick
命令并不是转移了原来的 commit,而是对 commit 的内容在新分支上进行复制,产生一个新的 commit。
如果想一次性合并多个 commit,如 commit 6c7f86a、7dd4dc3、24dcd32,可如下执行:
$ git cherry-pick 6c7f86a 7dd4dc3 24dcd32
这样就可一次性合并三个 commit。如果不想马上对捡过来的 commit 进行提交,可增加参数 --no-commit
,如下:
$ git cherry-pick 6c7f86a --no-commit
这样一来,捡过来的 commit 不会直接合并并提交,而是会出现在 index 暂存区。
十一、未提交代码暂存
Git 中代码的修改如果不想提交又想保存起来,可以使用 git stash
命令,把代码的改动(包括工作区和 index 区)放入暂存区,如果只想暂存某一部分代码,可以使用参数 -p
:
$ git stash -p
这时候终端会把每一个代码改动一一遍历,并询问:
$ Stash this hunk [y,n,q,a,d,j,J,g,/,e,?]?
这里的[y,n,q,a,d,j,J,g,/,e,?]分别代表的含义如下:
y - stage this hunk
n - do not stage this hunk
q - quit; do not stage this hunk nor any of the remaining ones
a - stage this hunk and all later hunks in the file
d - do not stage this hunk nor any of the later hunks in the file
j - leave this hunk undecided, see next undecided hunk
J - leave this hunk undecided, see next hunk
g - select a hunk to go to
/ - search for a hunk matching the given regex
e - manually edit the current hunk
? - print help
命令 git stash list
可以查看所有的代码暂存:
$ git stash list
stash@{0}: WIP on master: 049d078 added the index file
stash@{1}: WIP on master: c264051 Revert "added file_size"
stash@{2}: WIP on master: 21d80a5 added number to log
使用 git stash apply
可以应用最新的一个暂存,如果想应用其他代码暂存,可使用如下命令:
$ git stash apply stash@{2}
十二、标签
Git 标签分为两种类型:轻量标签和附注标签。轻量标签是指向提交对象的引用,附注标签则是仓库中的一个独立对象。
列出所有标签
$ git tag
如果想查看某个标签的具体信息,可以使用 git show
命令,带上标签名。
$ git show <标签名>
创建轻量标签
$ git tag <标签名>
创建附注标签
$ git tag -a <标签类型> -m “标签说明”
删除本地标签
$ git tag -d <标签名>
删除远程标签
$ git push origin :refs/tags/远程标签名
切换到打下某一标签时的代码
$ git checkout <标签名>
通常的 git push
不会将标签对象提交到 Git 服务器,我们需要进行显式的操作,如指定标签名将对应标签提交到 Git 服务器。
$ git push <远程主机名> <标签名>
也可将本地所有标签一次性提交到 Git 服务器。
$ git push -tags