有时我看到这样的合并冲突:
<<<<<<< HEAD
...lots of code
line changed by me
...lots of code
line changed by me
...lots of code
=======
>>>>>>> origin/master
如果我手动环顾四周,我可以找到新位置,但是我不知道代码是被移动还是被更改和移动(真正的冲突)。我只能重复上游移动,以查看除原始移动之外是否还进行了其他任何更改。
假设代码是位置无关的,我该如何更轻松地解决这种情况?
澄清,如果新位置位于其他文件中,则容易发生这种情况。
Git的合并操作,在您看到冲突时,正在逐个文件地工作。如果文件orig-file.ext
中的某些代码现在位于文件new-file.ext
中,则git merge
不会在这里为您提供帮助。1
您可以要做的一件事是使用git blame
(也称为git annotate
)查看在their分支上发生的提交,以查看代码的移动位置。您将需要在这里大量参考the git blame
documentation。但是,默认情况下,要轻松查找新代码,您需要知道新文件的名称。然后,Git将帮助您查找原始文件的名称。但是您已经知道原始文件的名称:您需要新文件的名称。幸运的是,有一个git blame
选项可以帮助您-至少有可能。这里没有任何保证。
您可以做的另一件事是使用 1git blame
。这实际上可能是您最好的选择。如果您确定在新代码中将要更改某些行,请使用git grep
在另一分支的尖端提交中查找该代码。这将立即告诉您新文件的文件名。
关于合并的注意事项
git grep
做出的两个分支进行相冲突的更改,使示例合并了相同的问题:git grep
请记住,提交与两个分支提示提交进行比较,以查看您所做的更改以及更改。 (请记住,每次提交都会保存all个文件的完整快照。)在我的情况下,我只提交了两次提交,一次提交在master
的工作方式是将某些合并基础
$ git checkout -b move-code master
(move some code, add, commit)
$ git checkout -b change-code master
(modify the same lines I moved; add and commit)
$ git merge move-code
Auto-merging wt-status.c
CONFLICT (content): Merge conflict in wt-status.c
Automatic merge failed; fix conflicts and then commit the result.
上,一次提交在git merge
。但总的来说,您会遇到类似这样的内容:change-code
这意味着提交共享的提交,在我的move-code
是best
o--o--...--I <-- move-code (HEAD)
/
...--o--H
\
o--o--...--J
的尖端提交H
和我的[C0的尖端提交i
可访问的所有提交之间) ]。最好的共享提交是合并基础。您可以使用move-code
:使Git打印出此合并基础提交的哈希ID。J
Git在此处打印的哈希ID是合并库的哈希ID。现在,找到合并基础(用2
change-cde
或通过注视git merge-base
打印的图形或您可能会发现的图形使用的东西),您可以
看到它是什么$ git merge-base --all move-code change-code 566a1439f6f56c2171b8853ddbca0ad3f5098770 命令,将[git]视为需要合并的内容:git merge-base
和:git log --graph
或:
git diff
然后:
git diff --find-renames <hash-of-H> <hash-of-I>
第一个显示
您更改了什么,第二个显示,或者在这种情况下,我移动了什么。这些是Git合并的更改,一次是一对文件。不幸的是,这显示的是:您更改代码,并且他们他们更改了什么
已删除
代码来自一个文件,在我的情况下,则是git diff --find-renames <hash-of-H> <hash-of-J>
。您相信他们不仅将代码从文件$ H=$(git merge-base --all change-code move-code); echo $H
566a1439f6f56c2171b8853ddbca0ad3f5098770
$ git diff --find-renames $H change-code
diff --git a/wt-status.c b/wt-status.c
index cc6f94504d..f2bf294275 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -117,6 +117,7 @@ static void status_printf_more(struct wt_status *s, const char *color,
{
va_list ap;
+ // this is status_printf_more
va_start(ap, fmt);
status_vprintf(s, 0, color, fmt, ap, NULL);
va_end(ap);
迁移到$ git diff --find-renames $H move-code
[much bigger diff, snipped. This shows both files I changed:
I moved function status_printf_more to wt-status.h.]
,而不仅仅是delete代码,而是将它们moved从文件wt-status.c
迁移到orig-file.ext
,就像我移动了一些代码一样。您必须在这里浏览整个diff输出,以找到将它们moved代码放入的文件。递归合并
,事情变得更加困难。尽管您可以在这里使用每个合并基础,但是没有正确的方法继续进行。请注意,如果您使用new-file.ext
方法,则不需要任何这些东西!使用git grep
git grep
移到_______的位置如何,都肯定会在其中包含wt-status.c
一词。然后:status_printf_more
将在其分支的
tip commit中显示所有,在这种情况下,在提交files
$ grep -e status_printf_more move-code
中,它们具有匹配的行。 (J
选项不是严格必需的,我只是在这里使用它。)这是我的情况:-e
就在这里,我们有答案:该函数现在位于move-code:wt-status.c: status_printf_more(s, c, "%s%.*s%s\n", how, len, padding, one);
move-code:wt-status.c: status_printf_more(s, c, "%s%.*s%s -> %s",
move-code:wt-status.c: status_printf_more(s, c, "%s%.*s%s",
move-code:wt-status.c: status_printf_more(s, color(WT_STATUS_HEADER, s), "%s", extra.buf);
move-code:wt-status.c: status_printf_more(s, GIT_COLOR_NORMAL, "\n");
move-code:wt-status.c: status_printf_more(s, color(WT_STATUS_UNTRACKED, s),
move-code:wt-status.c: status_printf_more(s, branch_status_color, "%s", on_what);
move-code:wt-status.c: status_printf_more(s, branch_color, "%s\n", branch_name);
move-code:wt-status.h:static void status_printf_more(struct wt_status *s, const char *color,
中。使用wt-status.h
git blame
通常以错误的方向工作:从
git blame
选项。它还有一个选项--reverse
-在一次特定提交时找到跨文件移动或复制的代码。3
在我的情况下,我认为更改了代码的文件是-C
,我认为move-code
从中移出了代码。所以我可以使用:wt-status.c
[如果执行此操作,则可以找到(部分)移动的行和名称git blame -C --reverse ${H}^..move-code wt-status.c
,这是我实际移动它们的地方。但是有一个
lot输出。我可以使用行号和wt-status.h
选项将其削减:
-s
$ git blame -C -s -L 112,139 --reverse ${H}^..move-code wt-status.c
请注意,似乎只有两行是“来自” d16f83787f3 wt-status.c 112) va_end(ap);
d16f83787f3 wt-status.c 113) }
d16f83787f3 wt-status.c 114)
d16f83787f3 wt-status.h 115) static void status_printf_more(struct wt_status *s, const char *color,
d16f83787f3 wt-status.h 116) const char *fmt, ...)
d16f83787f3 wt-status.c 117) {
d16f83787f3 wt-status.c 118) va_list ap;
d16f83787f3 wt-status.c 119)
d16f83787f3 wt-status.c 120) va_start(ap, fmt);
[more stuff, snipped]
,但是在这种情况下,这就足够了。
注意,提交的范围开始了一个提交提交之前
wt-status.h
(我们之前发现的合并基础)。这并非总是必要的,但是在这种情况下,因为我移动代码的提交是在$H
之后的提交,因此我也需要Git来查看提交$H
本身。