gpt4 book ai didi

git - 查找 merge 提交可以撤消分支之一的先前更改?

转载 作者:太空狗 更新时间:2023-10-29 14:05:01 24 4
gpt4 key购买 nike

这让我想起了下面的案例(基于一个真实的故事)以及它带来的未解决的问题。
问题是:是否有任何git命令(或shell脚本)可用于查找合并提交,该命令放弃其中一个分支对文件的所有更改,而只包含另一个分支的更改?
注意:“其他”分支可能会也可能不会更改所讨论的文件。如果对于两个分支都更改文件的一般情况没有解决方案,我也很高兴有一个解决方案,如果“另一个”分支没有更改文件内容(即,文件内容取自两个分支的共同祖先),如下例所示。
如需澄清,请阅读以下场景。
到目前为止发生了什么…
这里我们有一个简单的git历史。你可以从Randy Fay's "Gory Story" about git克隆它。

       e---f
/ \
-a---b---c---d--...-x-y-z <-master <-bob
\
g---h <-alice

爱丽丝和鲍勃都在做这个项目。他们不是git专业人员,但他们的公司有一个简单的git介绍。
历史就是这样过去的:
爱丽丝按 c,这会改变 main.cfeature.cfeature_test.c。然后她继续在 feature.cg中工作(局部)。
bob提交 he,但在 f中有冲突的更改。
鲍勃确实有合并冲突,所以他和爱丽丝谈了。
他们同意接受鲍勃的零钱,放弃爱丽丝的零钱。
鲍勃在某个地方听到了一些关于 main.c这样做的消息,于是他进入他最喜欢的搜索引擎,找到了一个so页面 github
bob执行 git pull。合并应用干净, ours看起来正确。他不碰也不知道,所以就不碰了。所以他很高兴把合并推到 git merge ours
注意,bob刚刚取消了alice关于 git merge -s ours的工作。他还删除了alice在 git merge -s ours master中添加的测试用例,因此他甚至不会得到一个失败的测试来提醒他这个问题。
从那时起发展就在继续,人们快乐地投入、推动和融合,直到……
alice在尝试将commit main.cfeature.c合并到 upstream/master时发现了问题,因为在commit feature.c之前,她对 feature_test.c的新更改不会干净地应用到旧的 g上。
诊断
我可以告诉你,爱丽丝很难找出她的合并冲突是从哪里来的。当她发现的时候,她不会为鲍勃高兴的。
要诊断她的合并冲突是从何而来并不容易,因为爱丽丝在历史上很容易看到,除了她之外,没有人接触过这些文件。例如, h将只显示alice(创建文件的)的commit master,但既不显示 feature.c也不显示 feature.c。在本例中,alice可能注意到列表中没有 c,但是在实际项目中,在几十个提交中发现一个丢失的提交并不是那么容易。
她的下一步可能是 git log -- feature.c这将告诉她commit b引入了问题。因此,她检查了犯罪:
$ git show --patch d
commit a69d49a390b9e92a0fcd60f0396d08a4b839a8c1
Merge: fb1a69b 6ad85a1
Author: Bob <bob@x.com>
Date: Tue May 17 15:20:37 2016 +0200

Merge branch 'master' into bob

$

什么?如果commit cbreak d甚至不包含任何更改,更不用说触及文件,那么它是如何实现的呢?但是,alice记得她可以显示两个提交之间的差异,因此她决定查看相对于其双亲 c(aka git bisect)和 d(aka d)引入的更改。
$ git diff d^1 d
$ git diff d^2 d
diff --git a/feature.c b/feature.c
index 2a8efa8..621e63a 100644
--- a/feature.c
+++ b/feature.c
@@ -1,4 +1,2 @@
feature 1
-modified feature 2
-feature 3
-feature 4
+feature 2
diff --git a/feature_test.c b/feature_test.c
index fbc719a..3d14bd1 100644
--- a/feature_test.c
+++ b/feature_test.c
@@ -1,4 +1,2 @@
test feature 1
-modified test feature 2
-test feature 3
-test feature 4
+test feature 2
diff --git a/main.c b/main.c
index e2f8683..2cd1198 100644
--- a/main.c
+++ b/main.c
@@ -1,6 +1,8 @@
line 1
line 2
-alice 3
-alice 4
+bob 3
+bob 4
line 5
line 6
+bob 7
+non 8
$

啊哈!这样您就可以看到合并提交实际上做了什么。看起来 feature.c实际上与 feature.c完全相同,并且 d中所有文件中的所有更改都将撤消。
现在,有人可能会说,这都是bob的错,因为他使用git命令时没有完全理解它们。然而,他并不是第一个这样做的人,责怪他也不会真正帮助任何人。
重要的是:在项目的历史中是否还有其他这样的情况,不显眼的合并提交会悄悄地从整个分支撤消工作?这将是特别“伟大”的一个分支,它修复了一个微妙的虫子,只发生一次每露水月,并花了很长时间来寻找修复。
在上述情况下,文件 d^1仅在其中一个分支中更改。因此在合并之后, f将重置为来自共同祖先的版本( d^2)。如果bob也对 c进行了不冲突的更改,那么上面的内容可能更难检测,因此它与共同祖先不同。这就是我在导言中所说的“一般情况”。
*名字变了。

最佳答案

首先,假设我们正在寻找的“坏”合并只有两个父级(octopus合并可以有>2个父级)。
如果合并提交删除了其中一个分支的更改,那么我们知道保留其更改的分支的头将与合并提交处于完全相同的状态,因为合并提交中没有添加其他更改。这意味着合并提交和合并提交的“成功”父级之间的差异将为空。
但是,在将分支A合并到分支B时也可能出现这种情况,其中分支B不包含分支A中未包含的额外提交(即head ^1==merge base)。我们可以检查这种情况并忽略这种合并。
下面是一个脚本,它将打印合并提交的提交引用列表,该列表将从当前签出分支中的所有提交中清除不同分支的任一侧:

#!/bin/bash

# Loop through each commit
for ref in $(git rev-list HEAD); do
# Get a list of the commit's parents
parents="$(git log --pretty=%P -n 1 $ref)"

# Merge commits have 2 or more parents. We'll ignore merge commits with
# more than 2 parents for now.
if [ $(echo "$parents" | wc -w) -eq 2 ]; then
merge_base="$(git merge-base $ref^{1..2})"
merge_diverging=1
merge_unchanging=0

# Loop through ref^1 and ref^2 (the two parents)
for i in 1 2; do
parent_ref="$(git rev-parse $ref^$i)"
diff_lines="$(git diff $parent_ref $ref | wc -l)"

# Check for merge commits where one parent is the base of the
# merge so we can ignore them, since a merge which doesn't diverge
# (i.e. made with `git merge --no-ff`) will have an empty diff on
# one side
if [ "$merge_base" == "$parent_ref" ]; then
merge_diverging=0
fi

# Find if either side of the merge has an empty diff
if [ $diff_lines -eq 0 ]; then
merge_unchanging=1
fi
done

if [ $merge_diverging -eq 1 ] && [ $merge_unchanging -eq 1 ]; then
echo $ref
fi
fi
done

关于git - 查找 merge 提交可以撤消分支之一的先前更改?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37279465/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com