$ git tag <tagName> <branchName>
这样会在分支 branchName 的末梢打上 tagName 的 tag
See Also 9.3 分支变基
See Also 8.1 使用标签标记里程碑
See Also 9.2 导出版本库
命令 git add -p
能够在不进入交互模式的情况下直接进入补丁模式。
补丁模式是 Git 中非常有用的模式,在补丁模式中 Git 会显示这些文件的当前内容与版本库的差异,然后可以据此决定是否添加这些修改到暂存区。
命令 git reset HEAD
可以将所有文件从暂存区移除(也可以是 git reset
,因为 HEAD
是默认参数),git reset -- /path/to/file
将单个文件从暂存区移除。
命令 git commit -a
会把已经纳入 Git 版本控制的文件提交,而不会添加尚未被跟踪的文件。
git diff
默认会比较工作目录树和暂存区的区别,因此如果已经把文件加入了暂存区,那么 git diff
命令是无法看到任何 diff 信息的。这时可以使用 git diff --cached
命令来比较暂存区和版本库之间的区别。
命令 git mv <old name> <new name>
打包了 mv <old name> <new name>
、 git add <new name>
和 git rm <old name>
三个操作。
$ git merge <branchName>
压合指的是 Git 将一条分支上的所有历史提交压合成一个提交,提交到另一条分支上。要小心使用压合提交,因为大多数情况下,每个提交都应该作为一个单独的条目存在于历史记录中。
如果某条分支上的所有提交都密切相关,应随后作为一个正题记录(在父分支上)时,适合作压合提交。
$ git merge --squash <branchName>
这条命令会将 branchName 分支上的全部提交压合成当前分支上的一个提交,但这个时候,这些改变还没有提交,需要再次输入 git commit
命令进行提交。
$ git cherry-pick <commit SHA-1>
中间跳过了几个 commit ,可能会要求处理冲突。可以带上 -n 参数,用于拣选多个提交,进行合并操作,等全部拣选完毕后输入 git commit
命令提交。
一旦发生冲突后,就会在发生冲突的文件里发现 <<<<<<< <branchName1>:<fileName>
,=======
和 >>>>>>> <branchName2>:<fileName>
这样的标识。
<<<<<<<
后面跟随的是当前分支 branchName1 中的代码。而 >>>>>>>
之前则是另一条分支 branchName2 上的代码。
可以使用 git mergetool
工具来解决复杂的冲突,不同的系统不同的环境会有不同的工具,Git 会尽可能的找到每一个合并工具。
也可以在设置里配置 merge.tool 的值
所有合并工具得到的结果应该都差不多,都是显示各冲突区域,供用户选取定夺。
解决了所有冲突后,Git 自动暂存修改,等待提交。
命令 git branch -m <old name> <new name>
可以用来重命名分支。
在 git log
后面可以跟上以下参数用于指定查找范围:
-<数字>
显示最近若干条提交--since
最近的时间内的提交--before
多少时间前的最后一个提交<commit1 SHA-1>..<commit2 SHA-1>
检索从 commit1 到 commit2 之间的提交(不包括 commit1)
-since
和 --before
参数接受大多数英文格式的日期。Git 工具本身能够识别诸如 "24 hours"、"1 minute"、"2008-10.01" 这样格式的日期,哪怕日期中间既有连字符又有句点。
第三种检索方式可以省略 <commit2 SHA-1>
,这时 commit2 就会被 HEAD 替代,也可以用 tag 名替代。
另一种指定版本的常见方法是指出它与另一版本的关系,此时有两种操作符可以使用:
- ^ 相当于回溯一个版本。
2222222^
相当于 2222222 的前一个版本;2222222^^
代表 2222222 的前第二个版本(也可以写作2222222^2
,^
其实是^1
的别名) - ~N 回溯 N 个版本。
2222222^
相当于222222~1
可以混合使用两种操作符。
在 git log
命令中加入 -p
参数,能够显示版本间的内容差异。
在 git diff
中指定版本范围和 git log
一样,唯一差别是 git diff
输出的是最老版本和最新版本之间的差异。
在 git diff
中使用标签作为参数,是一种获取发布版本之间代码量统计的好方法,通过加入一个 --stat
参数,可以计算出修改和删除的代码行数。如果只传入一个参数,Git 会默认把工作目录树作为参数。
命令 git blame
用于查看特定代码块的历史信息。通过传入 -L
参数可以缩小显示的范围,范围用 <start>,<end>
表示。范围的值可以是数字,可以是 +N,-N 的形式,也可以是正则表达式。同时,blame
命令也可以使用 指定查找范围 中的操作符:
$ git blame -L "/<\/body>/",-2 2222222^ -- hello.html
命令中的 --
符号是在通知 Git 查询指定文件。
命令 git blame
加入参数 -M
可以检测同一个文件内移动或复制的代码行,用同一个提交名称标识。加入参数 -C -C
可以检测文件之间的复制:
$ git blame -C -C cp.txt
Git 会输出初始的提交名称和初始的文件名。给 git log
传入参数 -C -C
也能显示复制信息,如果传入 -p
参数,git log
还会显示代码的具体变动。
在 git commit
命令中传入 -C <commit SHA-1>
参数,Git 会复用那个提交的 commit,如果传入的是小写的 c ,就会打开预设的编辑器,以便在已有的提交留言基础上编辑修改。
增补提交只能针对最后一个提交,如果想更正几个提交之前的某个错误,就需要用到 git revert
命令。
命令 git revert <commit SHA-1>
通过在版本库中创建一个“反向的”新提交来抵消原来提交的改动。在命令中加入 -n
参数可以制止 Git 立即提交反转结果,来进行多次反转。
通常,命令会启动默认编辑器并把默认信息加入其中,可以添加参数 --no-edit
直接使用默认的 commit 信息。
命令 git reset <commit SHA-1>
的默认参数是 HEAD ,可以使用 指定查找范围 中的操作符。如果传入 --soft
参数,Git 会暂存所有因果复位带来的差异,但不提交。用户可以修改这些内容再提交。
如果传入 --hard
参数,Git 会从版本库和工作目录同时删除提交,不可恢复。
命令 git rebase -i
能够以人机交互的方式改写历史记录。具体内容可以看 《Pro Git》 的 第六章第四节 《重写历史》 和 《Git 魔法》的第五章 《关于历史》 。
在本地版本库中,远程版本库的别名默认是 origin 。它是克隆远程版本库时自动生成的。
命令 git remote add <别名> <版本库全称>
用于为远程版本库添加别名。
命令 git remote rm
用于删除别名。
$ git checkout <tagName>
这时会检出直到 的历史到 (no branch)
上。
$ git [branch|checkout -b] <branchName> <tagName>
这时就会检出到 tagName 为止的代码到 branchName 分支
Git 版本库里存储了所有的东西,由此带来的问题是偶尔会留下一些没有用的数据。比如 --amend
时 Git 也会记住原来的版本;或者用 git branch -D
删除一个试验分支时,Git 依旧会保留该分支上的内容。
命令 git gc
整理版本库以优化 Git 内部存储历史记录,一个月清理一次,或者大约100次提交清理一次即可。它不改变历史记录,只改变历史记录的存储方式。
在命令中带上 --aggressive
参数可使版本库得到进一步的优化。这会增加时间,但值得尝试。
Git 在增量存储单元 (delta) 中存储修改。一般情况下, git gc
命令运行时会压缩这些增量存储单元,但是不会重新计算它们。如果使用 --aggressive
参数,则 Git 会重新计算它们。
$ git archive --format tar \
--prefix=mysite-1.0/ 1.0 \
| gzip > mysite-10.tar.gz
--format
指明要产生 tar 格式的输出;--prefix
指明包中所有东西都放到 mysite-1.0/ 目录下;1.0
指明需要归档的标签名称。
也可以用
$ git archive --format zip \
--prefix=mysite-1.0/ 1.0 \
> mysite-10.zip
来产生一个 zip 文件。
要同步分支之间的历史,除了使用 Git 提供的合并分支功能,还可以使用变基操作。
$ git rebase <branchName>
变基的意思是“改变分支的基底”,把一条分支上的修改在另一条分支的末梢重现。你可以把这种方式看作是基于一个新的基点,重演分支上发生过的改动。
除了同步历史以外, git rebase
还拥有修改历史的能力,具体可以参考 6.7 重新改写历史记录。
命令 git rebase
命令还提供了一个 --onto
参数,用于将分支3与分支2的提交记录差值变基到分支1上。
例如,有三条分支,主分支 master ,从 master 拉出来的 contacts 和从 contacts 拉出来的 search 分支。
当完成 search 分支上的代码时,发现不需要任何在 contects 分支上完成的改动,搜索功能即可运行。
这时就可以输入以下命令,将 search 分支变基到 master 。
$ git rebase --onto master contacts search
这个命令是将 search 分支从 contacts 分支剥离,移动到主分支上,如果要合并 search 分支上的内容到 master 上,不需要 contacts 上的任何东西,可以使用此方法。当然,search 分支要完全独立于 contacts 分支,尽量避免变基到 master 时出现合并冲突。
还可以使用 6.2 指定查找范围 中提到的 提交范围参数 ,来做一些其他有趣的事情,比如抹消倒数第二个提交。
$ git rebase --onto HEAD^^ HEAD^ HEAD
重现是指记录分支末梢变化的情况,并予以复现。第五章理解和使用分支中介绍过,分支本质上只是指向最新提交的指针。重现功能可以记录和跟踪所有这些指针的变化。通过使用它,你能找到想要的提交,并据此恢复分支。
命令 git reflog
的输出结果是按时间倒序排列的,类似 git log
。它的职能只是列出重现记录,而想要恢复这个记录的步骤可以参考 8.1 使用标签标记里程碑。
注意,在 9.1 压缩版本库 中提到的 git gc
会删除比较旧的重现记录,阀值通常是30天,可以通过修改配置 gc.reflogExpireUnreachable 的值来改变有效期。
同时,除非修改 gc.reflogExpire 的值,重现记录通常会在 90 天后过期。
命令 git bisect
基于一个已知的坏提交和一个已知的好提交,逐步排查版本库中的历史记录。它带领你在版本库中的历史上标出哪些是好提交哪些是坏提交,直到最后找出那个引进 Bug 的提交。
首先运行 git bisect start <某个提交或标签>
来开始二分查找,然后调用 git bisect bad|good <某个提交或标签>
进行标记。如果没有输入提交或标签,则默认为 HEAD 。
当找到 Bug 后,需要回到 HEAD 进行修补,这时候使用命令 git bisect reset
即可。
如果希望直观的理解代码的演进历史,可以使用 git bisect visualize
命令来可视化记录。
如果喜欢文本输出,可以使用 git bisect log
存储成为一个文件;删除该文件中刚才错误的标识操作及其后的所有记录;然后将该文件作为命令 git bisect replay <某一文件>
的参数,让 Git 重新执行,直到刚才错误标识之前一步。
命令 git bisect
还可以适时自动运行自动测试套件。为了使用这一功能,需要构造一个可以在命令行运行的脚本,且该脚本在测试通过是返回 0 ,测试失败时返回一个正数(这个正数通常是 1),如果要跳过一条提交并让 Git 二分查找自动移向下一条提交,则应返回 125 。
命令 git bisect run
可以用来自动运行这个脚本。例如:
$ git bisect start HEAD 1.0
$ git bisect run /work/run-test
推荐将测试文件放在仓库之外,以确保 Git 不会改变 git bisect
正在运行的脚本文件。
$ git config --global <configName> <configValue>
只作用于特定版本库的配置
$ git config <configName> <configValue>
$ git add -u [<some path> [<some path>]]
$ git checkout HEAD <some file> [<some file>]
$ git reset HEAD <some file> [<some file>]
$ git commit -c
如果不想修改,直接使用的话,就将 -c
参数变为 -C
参数。
你可以从版本库的任何一个版本开始创建新分支。起始点可以用 分支名称、提交名称或者标签名称。
$ git branch <new branch> <start branch>
加入 -f
参数可以创建同名新分支,覆盖已有分支。
加入 -m
用于移动或重命名分支, -M
用于重命名时覆盖已有分支。
有关 hook 的内容,可以看 《Pro Git》 的 7.3 自定义 Git - Git挂钩。
See Also 7.2 自定义 Git - Git属性#二进制文件
See Also 7.2 自定义 Git - Git属性#关键字扩展