为修改后的帅哥获取新位置

问题描述 投票:1回答:1

有时我看到这样的合并冲突:

<<<<<<< HEAD
...lots of code
line changed by me
...lots of code
line changed by me
...lots of code
=======
>>>>>>> origin/master

如果我手动环顾四周,我可以找到新位置,但是我不知道代码是被移动还是被更改和移动(真正的冲突)。我只能重复上游移动,以查看除原始移动之外是否还进行了其他任何更改。

假设代码是位置无关的,我该如何更轻松地解决这种情况?

澄清,如果新位置位于其他文件中,则容易发生这种情况。

git merge-conflict-resolution
1个回答
0
投票

Git的合并操作,在您看到冲突时,正在逐个文件地工作。如果文件orig-file.ext中的某些代码现在位于文件new-file.ext中,则git merge不会在这里为您提供帮助。1

可以要做的一件事是使用git blame(也称为git annotate)查看在their分支上发生的提交,以查看代码的移动位置。您将需要在这里大量参考the git blame documentation。但是,默认情况下,要轻松查找新代码,您需要知道新文件的名称。然后,Git将帮助您查找原始文件的名称。但是您已经知道原始文件的名称:您需要新文件的名称。幸运的是,有一个git blame选项可以帮助您-至少有可能。这里没有任何保证。

您可以做的另一件事是使用git blame。这实际上可能是您最好的选择。如果您确定在新代码中将要更改某些行,请使用git grep在另一分支的尖端提交中查找该代码。这将立即告诉您新文件的文件名。


1

如果whole file重命名,Git will会在这里为您提供帮助,因为它将与your分支中的文件更改匹配their分支中的文件重命名。您将得到一个修改/重命名冲突。但这不是这里发生的事情。
关于合并的注意事项

我通过对Git的Git存储库克隆中的git grep做出的两个分支进行相冲突的更改,使示例合并了相同的问题:

git grep

请记住,master的工作方式是将某些

合并基础

提交与两个分支提示提交进行比较,以查看您所做的更改以及更改。 (请记住,每次提交都会保存all个文件的完整快照。)在我的情况下,我只提交了两次提交,一次提交在$ 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代码放入的文件。

2
如果打印出多个合并基数,则您可能执行了

递归合并

,事情变得更加困难。尽管您可以在这里使用每个合并基础,但是没有正确的方法继续进行。请注意,如果您使用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通常以错误的方向工作:从

last提交(或您指定的某些提交)向后,这是Git的自然方向。但是,它具有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
$ 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本身。
© www.soinside.com 2019 - 2024. All rights reserved.