git 提交文件中的部分修改

1. 概述

在 Git 提交一个文件的时候,有时候会在同一个文件中,包含两个不同功能的修改,或者一个功能完成了,而别的部分还没有完善不应该进入代码库,这时候如果使用git add file-name的话,会将这个文件中的所有更新都提交,达不到上述的需求。针对这种场景,git 提供了更细粒度的提交命令git add -p,可以分部分提交一个文件中的更新代码块,实测能满足常见的需求。这里简要记录一下如何使用这个命令。

2. 实现命令

2.1 原理解释

git 中用”hunk”来表示一个文件中邻近区域中的代码修改块,比如用git diff 查看修改时,两个@@符号分割的一个区域就是一个hunk,其中行首是-,颜色为红色的为删去的行,而行首为+,颜色为绿色的为增加的行。
git_hunk_vis

需要注意的是,git有一套默认的将文件中所有修改分成不同hunk的机制,但我们也可以将默认机制分的太大的hunk分割为多个小的hunk,这样能更精确地控制提交的粒度。

部分提交文件修改的原理简单来说是将所有的修改分成不同的hunk,通过对每个hunk来进行是否提交的判断,从而完成我们的需求。具体命令下面详细讲述。

2.2 命令详解

git add -p filename就可以进入交互式的操作界面,所有的操作在该界面完成,其中-p是patch的缩写。界面如下:

这里会自动载入第一个hunk,显示了修改的代码行,最底下一行显示了这是8个hunk里面的第一个,然后有一些选项让我们选择,这时候输入?,按会车会显示help信息:

所有命令的含义如下:

1
2
3
4
5
6
7
8
9
10
11
y - 将当前的hunk进行提交
n - 不提交当前hunk
q - 退出交互式界面,不提交当前hunk以及后面的所有hunk
a - 提交当前hunk以及后面的所有hunk
d - 不提交当前hunk以及后面的所有hunk,效果与q一样,也会退出交互式界面
g - 选择一个hunk并跳转过去,输入后会列出所有hunk的编号,输入编号就跳转到对应的hunk
/ - 输入一个正则表达式,选择一个包含搜索词的hunk进行跳转
j - 暂时不确定是否保存当前hunk,跳转到下一个没确定的hunk
J - 暂时不确定是否保存当前hunk,跳转到下一个hunk
e - 手动修改hunk块的内容,将`-` 开头的行替换为 ` `则不会删去这行,删除`+`为首的行则不提交这个新增,以`#`开始的行会被忽略
? - 显示帮助信息

详细阅读上面的说明,结合实际的操作,就能掌握这个命令的所有用法。

简单来说,使用y来提交当前hunk,使用n来忽略当前hunk,如果hunk代码块太大,输入s会将其分割为小的hunk,在上面继续操作,hunk间上下跳转用vim的快捷键kj,要退出则输入q

3. 参考

  1. https://stackoverflow.com/questions/1085162/commit-only-part-of-a-file-in-git