Git常用命令
一些 git 常用命令总结。
Git常用命令
仓库管理
Clone 远程仓库
1 | git clone <repo url> |
url 有两种:
https://github.com/username/reponame.git
git@github.com:username/reponame.git
Clone 远程仓库指定分支
1 | git clone -b <remote branch name> <repo url> |
Clone 含子模块的仓库
若需要克隆含有子模块的仓库,直接进行克隆无法拉取子模块的代码,可加上 --recursive
参数,如:
1 | git clone --recursive <repo url> |
或者:
1 | git clone <repo url> |
查看已添加的远程仓库
1
git remote -v
查看远程仓库的信息
1 | git remote show <repo name> |
例如:
1 | git remote show origin |
添加远程仓库
1 | git remote add <repo name> <repo url> |
repo name
为远程仓库的本地名称,可自定义,相当于给 url 对应的仓库起了个别名,对于 git clone
的仓库在本地的名称默认为 origin
删除远程仓库
1 | git remote rm <repo name> |
修改远程仓库
1 | git remote set-url [--push|--add|--delete] <repo name> <new url> [<old url>] |
1 | 可选项: |
例如:
1 | git remote set-url origin git@github.com:username/reponame.git |
拉取远程仓库
1 | git pull [<repo name> <branch name>] |
这里的 repo name
和 branch name
都是远程的
推送远程仓库
1 | git push [<repo name> <branch name>] |
这里的 repo name
是远程的, branch name
为本地分支名
例如:
1 | git push origin master |
分支管理
查看分支
查看本地分支
前面有 "*" 标记的为当前所在分支
1 | git branch |
查看远程分支
1 | git branch -r |
查看所有分支
查看所有分支,包括本地的和远程的
1 | git branch -a |
删除分支
删除远程分支
推送一个空分支以删除远程分支,本地分支依然存在
1 | git push <repo name> :<remote branch name> |
或者
1 | git push <repo name> --delete <remote branch name> |
repo name
为仓库的本地别名,默认为 origin
例如:
1 | git push origin :develop |
删除本地分支
1 | git branch -d <branch name> |
-d
选项只能删除已参与了合并的分支,对于未合并的分支是无法删除的,如果想强制删除一个分支,可以使用 -D
选项。
切换分支
1 | git checkout <branch name> |
创建分支
创建本地分支
1 | git branch <Branch Name> |
创建本地分支并切换到新分支
1 | git checkout -b <branch name> |
创建远程分支
1 | git push [-u] <repo name> <local branch name>:<remote branch name> |
例如:
提交本地 dev 分支作为远程的 develop 分支,实际应用中 应该保持本地分支名称与远程分支名称一致
1 | git push origin dev:develop |
如果本地分支名称与远程分支名称不一致,在 git push
时会有如下提示:
1 | git push |
- 如果使用
git push origin HEAD:develop
,则会将当前 HEAD 指向的 dev 分支 push 到远程的 develop 分支 - 如果使用
git push origin dev
,则会在远程仓库中创建一个名为 "dev" 的新分支(如果原先不存在),并将当前本地的 dev 分支推送到远程的 dev 分支 - 如果推送时使用
-u
选项,Git 不但会把本地的dev
分支内容推送的远程新的develop
分支,还会把本地的dev
分支和远程的develop
分支关联起来,以后在推送或者拉取时就可以使用简化命令git push|pull
。
关联本地分支与远程分支
如果已添加远程仓库,但是本地分支与远程分支没有关联,使用 git pull
会导致失败:
1 | git pull |
错误提示也给出解决方法:
方法一:指定要拉取的仓库的分支
1 | git pull <repo name> <branch name> |
这里我把 remote
写成 repo name
是为了与上面保持一致,其含义也是相同的,都是表示远程仓库在本地的别名。一般而言,远程远程仓库名为项目名称,而在本地代表该仓库的名称默认为"origin"
方法二:关联本地分支与远程分支
1 | git branch --set-upstream-to=<repo name>/<remote branch name> <local branch name> |
在关联本地分支与远程分支之后,就不用每次都指定仓库名和分支名了,只需执行 git pull
查看本地分支与远程分支的跟踪关系
1 | git branch -vv |
可看到当前分支与对应的远程关联分支
合并分支
合并本地分支
1 | git merge <branch name> |
例如:将 "dev" 分支合并到当前分支
1 | git merge dev |
合并远程分支
先检出仓库
1
git clone <url>
默认为 master 分支,然后查看全部的远程分支
1
git branch -r
例如:
1
2
3git branch -r
origin/develop
origin/master切换分支,要合并到哪个分支就切换到哪个分支
如果要合并到 master 分支,就不用切换
合并分支
例如:将远程的 develop 分支合并到 master 分支
1
git merge origin/develop
推送合并后的分支
1
git push
分支重命名
本地分支重命名
1 | git branch -m <old name> <new name> |
远程分支重命名
重命名远程分支对应的本地分支
1
git branch -m <old name> <new name>
删除远程分支
1
git push --delete <origin> <old name>
上传新命名的本地分支
1
git push <origin> <new name>
把修改后的本地分支与远程分支关联
1
git branch --set-upstream-to=<origin>/<new name>
工作现场的保存与恢复
分支修改相互影响
现象:
假设当前有两个分支,一个 master 分支,一个 dev 分支。 master 分支的工作区和暂存区( stage )是干净的,也即 nothing to commit, working tree clean
, dev 分支由 master 分支 checkout 并创建得到。假设此时在 dev 分支下创建一个文件 touch abc.txt
,然后切回 master 分支,会发现 master 分支下的工作区也包含该文件。
原因:
git 切换分支时会把未 add 或未 commit 的内容带过去。未 add 的内容不属于任何一个分支,未 commit 的内容也不属于任何一个分支,也就是说,对于所有分支而言,工作区和暂存区都是共享的。未 add 的内容会存放在工作区,已 add 且未 commit 的内容会存放在暂存区( stage ),对于 add 后已 commit 的内容独立存放当前分支。
解决方法:
总的来说,只要保证工作区和暂存区是干净的就可以了。
具体来说通常有以下两种方法:
- 使用
git add
和git commit
提交修改,那么此时使用git status
检查工作区和暂存区就是干净的 - 如果当前分支上的工作还未完成或者还不能提交,但又需要去修改其它分支的,这时可以把当前分支的工作现场保存起来。使用
git stash
可以保存当前暂存区的内容,此时使用git status
检查工作区和暂存区就是干净的,详情查看工作现场的保存与恢复。
保存工作现场
git stash
可以保存当前工作现场,实际上是保存当前暂存区( stage )的内容,对于未 add (未跟踪)的文件的修改不会保存(不会隐藏)。stash 功能,可以让我们暂时放下当前分支的工作,转而切换到另一分支进行其它工作,在完成其它分支工作后,可以切回该分支恢复现场继续未完成的工作。
注意:如果当前分支中,不存在未 add 的文件,执行 git stash
保存工作现场后,此时使用 git status
检查工作区和暂存区就是干净的,如果存在未 add 的文件,那么工作区是不干净的而暂存区是干净的。
举例来说,如果修改发生在新文件中且已 add,那么 git stash
后工作区将不会看到该新文件;如果修改发生在新文件中且未 add ,那么 git stash
不会对该文件进行任何操作,该文件依然在工作区中可见。
可以多次 stash ,包括同一分支多次 stash ,不同分支多次 stash。
查看保存的工作现场
1 | git stash list |
恢复工作现场
恢复现场有两种方法:
- 使用
git stash apply
恢复,但是恢复后,stash 内容并不删除,需要用git stash drop
来删除 - 使用
git stash pop
,恢复的同时把 stash 内容删除,这时用git stash list
就看不到已经 pop 了的工作现场了
恢复的时候,先用 git stash list
查看,然后用 git stash apply <stash@{id}>
或者 git stash pop <stash@{id}>
恢复指定的 stash ,例如 git stash apply stash@{0}
标签管理
像其他版本控制系统(VCS)一样,Git 可以给仓库历史中的某一个提交打上标签,以示重要。比较有代表性的是人们会使用这个功能来标记发布结点(v1.0 、 v2.0 等等)。
列出标签
在 Git 中列出已有的标签只需要输入 git tag
(可带上可选的 -l
选项 --list
):
1 | git tag |
可以按照特定的模式查找标签。例如,如果只对 1.8.5 系列感兴趣,可以运行:
1 | git tag -l "v1.8.5*" |
创建标签
Git 支持两种标签:轻量标签(lightweight)与附注标签(annotated)。
轻量标签很像一个不会改变的分支——它只是某个特定提交的引用。
而附注标签是存储在 Git 数据库中的一个完整对象, 它们是可以被校验的,其中包含打标签者的名字、电子邮件地址、日期时间, 此外还有一个标签信息,并且可以使用 GNU Privacy Guard (GPG)签名并验证。 通常会建议创建附注标签,这样你可以拥有以上所有信息。但是如果你只是想用一个临时的标签, 或者因为某些原因不想要保存这些信息,那么也可以用轻量标签。
Annotated Tags 附注标签
使用 git tag
命令创建附注标签时需要指定 -a
选项:
1 | git tag -a v1.4 -m "my version 1.4" |
-m
选项指定了一条将会存储在标签中的信息。如果没有为附注标签指定一条信息,Git 会启动编辑器要求你输入信息。
通过使用 git show
命令可以看到标签信息和与之对应的提交信息:
1 | git show v1.4 |
输出显示了打标签者的信息、打标签的日期时间、附注信息,然后显示具体的提交信息。
Lightweight Tags 轻量标签
轻量标签本质上是将 commit checksum 存储到一个文件中,没有保存任何其他信息。创建轻量标签,不需要使用 -a
、-s
或 -m
选项,只需要提供标签名字:
1 | git tag v1.4-lw |
这时,如果在标签上运行 git show
,你不会看到额外的标签信息。命令只会显示出提交信息:
1 | git show v1.4-lw |
后期打标签
你也可以对过去的提交打标签。假设提交历史是这样的:
1 | git log --pretty=oneline |
现在,假设在 v1.2 时你忘记给项目打标签,也就是在 "updated rakefile" 提交。你可以在之后补上标签。 要在那个提交上打标签,你需要在命令的末尾指定提交的校验和(或部分校验和):
1 | git tag -a v1.2 9fceb02 |
可以看到你已经在那次提交上打上标签了:
1 | git tag |
共享标签
默认情况下,git push
命令并不会传送标签到远程仓库服务器上。在创建完标签后你必须显式地推送标签到共享服务器上。这个过程就像共享远程分支一样,你可以运行 git push origin <tagname>
1 | git push origin v1.5 |
如果想要一次性推送很多标签,也可以使用带有 --tags 选项的 git push 命令。这将会把所有不在远程仓库服务器上的标签全部传送到那里。
1 | git push origin --tags |
现在,当其他人从仓库中克隆或拉取,他们也能得到你的那些标签。
删除标签
删除本地仓库标签
1 | git tag -d v1.4-lw |
注意上述命令并不会从任何远程仓库中移除这个标签。
删除远程仓库标签
第一种方法是使用
git push <remote> :refs/tags/<tagname>
:1
2
3git push origin :refs/tags/v1.4-lw
To /git@github.com:schacon/simplegit.git
- [deleted] v1.4-lw
上面这种操作的含义是,将冒号前面的空值推送到远程标签名,从而高效地删除它。
第二种更直观的删除远程标签的方式是:
1
git push origin --delete <tagname>
检出标签
如果你想查看某个标签所指向的文件版本,可以使用 git checkout
命令, 虽然这会使你的仓库处于"分离头指针(detacthed HEAD)"的状态——这个状态有些不好的副作用:
1 | git checkout 2.0.0 |
在"detacthed HEAD"状态下,如果你做了某些更改然后提交它们,标签不会发生变化,但你的新提交将不属于任何分支,并且将无法访问,除非通过确切的提交哈希才能访问。因此,如果你需要进行更改,比如你要修复旧版本中的错误,那么通常需要创建一个新分支:
1 | git checkout -b version2 v2.0.0 |