您的位置:首页 > 其它

使用 git add -p 整理 patch

2020-06-01 00:29 316 查看

背景

当我们修改了代码准备提交时,本地的改动可能包含了不能提交的调试语句,还可能需要拆分成多个细粒度的

pactch

本文将介绍如何使用

git add -p
来交互式选择代码片段,辅助整理出所需的
patch

官方介绍

先贴个帮助信息供参考

英文版本:

-p, --patch
Interactively choose hunks of patch between the index and the work tree and add them to
the index. This gives the user a chance to review the difference before adding modified
contents to the index.

This effectively runs add --interactive, but bypasses the initial command menu and
directly jumps to the patch subcommand. See “Interactive mode” for details.

中文版本:

-p, --patch
交互地在索引和工作树之间选择补丁块并将它们添加到索引中。这让用户有机会在将修改后的内容添加到索引之前查看差异。

这可以有效地运行 add --interactive,但是会绕过初始命令菜单,而直接跳转到 patch 子命令。有关详细信息,请参见`‘交互模式’'。

demo 视频版

以下文字版例子对应的视频演示

demo 文字版

我们造个例子来说明,假设我们本次完成了两个功能,fun1 和 fun2,希望分开提交。另外在修改过程中还引入了一些调试的打印,是不需要提交的。

代码的

diff
如下

--git a/demo.c b/demo.c
index 0473c1a..76cfb22 100644
--- a/demo.c
+++ b/demo.c
@@ -1,16 +1,31 @@
#include <stdio.h>

+void fun1()
+{
+       printf("before hello world\n");
+}
+
void demo()
{
;
}

+void fun2()
+{
+       printf("after hello world\n");
+}
+
int main()
{
+       fun1();
printf("hello world\n");
+       printf("debug %s %d\n", __func__, __LINE__);
printf("hello world\n");
printf("hello world\n");
printf("hello world\n");
+       printf("debug %s %d\n", __func__, __LINE__);
printf("hello world\n");
+       fun2();
demo();
+       printf("debug %s %d\n", __func__, __LINE__);
}

此时直接

git add
会把整个文件的改动都加进来,不符合需求。

这正是

patch mode
发挥作用的地方,我们可以挑选一部分改动进行提交。

输入

git add -p
进入
patch mode
, 此时
git
会自动将改动切分成多个片段,并展示第一个片段,提示你进行选择。

提示语句是

Stage this hunk [y,n,q,a,d,/,s,e,?]?

这些字母都是什么意思呢? 输入

?
回车,可以查看详细的帮助信息。

英文版本:

y - stage this hunk
n - do not stage this hunk
q - quit; do not stage this hunk or any of the remaining ones
a - stage this hunk and all later hunks in the file
d - do not stage this hunk or any of the later hunks in the file
g - select a hunk to go to
/ - search for a hunk matching the given regex
j - leave this hunk undecided, see next undecided hunk
J - leave this hunk undecided, see next hunk
k - leave this hunk undecided, see previous undecided hunk
K - leave this hunk undecided, see previous hunk
s - split the current hunk into smaller hunks
e - manually edit the current hunk
? - print help

中文版本:

y - 暂存此区块
n - 不暂存此区块
q - 退出;不暂存包括此块在内的剩余的区块
a - 暂存此块与此文件后面所有的区块
d - 不暂存此块与此文件后面所有的 区块
g - 选择并跳转至一个区块
/ - 搜索与给定正则表达示匹配的区块
j - 暂不决定,转至下一个未决定的区块
J - 暂不决定,转至一个区块
k - 暂不决定,转至上一个未决定的区块
K - 暂不决定,转至上一个区块
s - 将当前的区块分割成多个较小的区块
e - 手动编辑当前的区块
? - 输出帮助

对于我们的例子,

git
第一次自动给出的
hunk
很大,可以先执行
s
分割下。分割后第一个区块就只包含增加的
fun1
函数了。

/* 太占篇幅,此处省略原始 hunk */
Stage this hunk [y,n,q,a,d,/,s,e,?]? s /* 询问我们对第一个片段的处理,我们觉得太大,按 s 要求分割 */
Split into 7 hunks. /* 可以看到,s 让 git 将原始片段进一步切分成了 7 个片段,接下来就是自动展示第一个片段 */
@@ -1,7 +1,12 @@
#include <stdio.h>

+void fun1()
+{
+       printf("before hello world\n");
+}
+
void demo()
{
;
}

Stage this hunk [y,n,q,a,d,/,j,J,g,e,?]?  /* 询问我们对第一个片段的处理 */

输入

y
回车选中这个
fun1
的改动,
git
就会自动展示下一个片段,继续询问我们。

这样对片段使用

y
n
,我们就可以只挑选出涉及
fun1
的改动,当我们确认后续没有
fun1
相关的改动时,就可以按
q
退出挑选了。

此时

git status
可以看到部分改动在暂存区中。

$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)

modified:   demo.c

Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)

modified:   demo.c

使用

git diff --cached
可以具体确认要提交的内容,是否符合我们的预期,只包含
fun1
的改动,不包含
fun2
和调试语句。

$ git diff --cached
diff --git a/demo.c b/demo.c
index 0473c1a..b9fd4d4 100644
--- a/demo.c
+++ b/demo.c
@@ -1,5 +1,10 @@
#include <stdio.h>

+void fun1()
+{
+       printf("before hello world\n");
+}
+
void demo()
{
;
@@ -7,6 +12,7 @@ void demo()

int main()
{
+       fun1();
printf("hello world\n");
printf("hello world\n");
printf("hello world\n");

确认无误就可以提交第一个

patch
, 即
fun1
的改动了。

git commit -m "fun1"

接下来继续使用

git add -p
,配合
s
,
y
,'n'就可以进一步挑选出
fun2
的改动了。

如果要挑选的改动比较明确,可以直接使用

/
来搜索到目标
hunk
,省去逐个片段判断的麻烦。例如执行
/fun2
来搜索包含
fun2
的代码片段。

git add -p
挑选完之后,建议使用
git diff --cached
确认下,或者在提交之后
git show
确认下改动,如有错漏,及时修正,多退少补。

大部分情况使用

s y n
就足够了。但如果有些改动是混合在一起的,无法使用
s
来分割,那就得用
e
来手工编辑了,下回分解吧。

blog: https://www.cnblogs.com/zqb-all/p/13020293.html 公众号:https://sourl.cn/MDcrJA

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: