如何列出包含等效提交的分支 [英] How to list branches that contain an equivalent commit

查看:98
本文介绍了如何列出包含等效提交的分支的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在之前的问题中,有人提供了一个用于查找包含EXACT commit的分支的答案:

如何列出包含给定提交的分支

接受的答案突出显示,这仅适用于EXACT提交ID,而不适用于相同的提交。有人进一步表示,Git Cherry可以用来解决这个问题。

Git樱桃SEEMS适合相反;找到不向上游推送的提交。如果我不知道哪个分支创建了它,以及什么是上游,这是无用的。所以我不明白它将如何帮助解决这个问题。



有人可以解释/提供如何使用git cherry查找包含特定提交的等价物的所有分支的示例吗?在你能回答哪个分支包含等价提交的问题之前,你必须确定哪些提交是等价的。一旦你有了这些,你只需在每个提交中使用 git branch --contains



不幸的是,没有100%可靠的方法来确定等价提交。



最可靠的方法是检查提交引入的变更集的修补程序标识。这就是 git cherry git log --cherry git log --cherry -mark 依赖。在内部,他们都调用 git patch-id 。修补程序ID就是变化规范化差异的SHA1。任何引入相同更改的提交都将具有相同的补丁ID。此外,任何引入大多相同更改的提交(仅在文件中应用的空白或行号不同)将具有相同的补丁ID。如果两次提交具有相同的补丁ID,则几乎可以保证它们是相同的 - 您几乎不会通过补丁ID获得误报。假阴性经常发生。任何时候你做 git cherry-pick 并且必须手动解决合并冲突时,你可能会引入变更集中的差异。即使是1个字符的变化也会导致生成不同的补丁ID。



按照Chronial的建议检查补丁ID需要脚本。首先计算原始提交的修补程序ID,类似于

(注意 - 脚本未经测试,应该相当接近正常工作)

  origCommitPatchId = $(git diff ORIG_COMMIT ^!| git patch-id | awk'{print $ 1}')

现在您将不得不搜索历史记录中的所有其他提交并计算它们的修补程序ID,并查看它们中的任何一个是否为在$(git rev-list --all)

testPatchId = $时,

  $(git diff $ {rev} ^ 1 .. $ {rev} | git patch-id | awk'{print $ 1}')
if [$ {origCommitPatchId}=$ {testPatchId}] ;然后
echo$ {rev}
fi
done

现在你有了SHA列表,你可以将它们传递给 git branch -a --contains



如果由于合并冲突而导致上述不适用于您?

好吧,还有其他一些你可以尝试的东西。通常,当您选择提交时,提交中的原始作者姓名,电子邮件和日期字段将保留。所以你会得到一个新的提交,但作者信息将是相同的。



所以你可以从你原来的提交中获得这个信息:

  git log -1 --pretty =%an%ae%adORIG_COMMIT 

然后和以前一样,你必须经历历史中的每一次提交,才能打印出相同的信息并进行比较。 可能会给你一些额外的匹配。



您也可以使用 git log --grep = ORIG_COMMIT ,它可以找到提交消息中引用ORIG_COMMIT的任何提交。



如果没有这些工作,您可以尝试查找随镐头引入的特定行,或者可以 git log --grep 为其他可能在提交消息中唯一的其他内容。

如果这听起来很复杂,那就是。这就是为什么我告诉人们尽可能避免使用樱桃挑选。 git branch --contains 非常有价值,易于使用且100%可靠。其他解决方案甚至没有接近。


In a prior question someone provided an answer for finding branches that contained an EXACT commit:

How to list branches that contain a given commit

The accepted answer highlighted that this only works for an EXACT commit id, and not for an identical commit. It was stated further that Git Cherry can be used to solve this.

Git cherry SEEMS to be geared for the reverse; finding commits NOT pushed upstream. This is useless if I don't know which branch created it and what is upstream of what. So I don't see how it's going to help solve this problem.

Can someone explain / provide an example of how to use git cherry to find all branches that contain the 'equivalent' of a specific commit?

解决方案

Before you can answer the question of which branches contain an equivalent commit you have to determine "which commits are equivalent". Once you have that, you simply use git branch --contains on each of the commits.

Unfortunately, there is no 100% reliable way to determine equivalent commits.

The most reliable method is to check the patch id of the changeset introduced by the commit. This is what git cherry, git log --cherry, and git log --cherry-mark rely on. Internally, they all call git patch-id. A patch id is just the SHA1 of the normalized diff of changes. Any commit that introduces identical changes will have the same patch id. Additionally, any commit that introduces mostly identical changes that differ only in whitespace or the line number where they apply in the file will have the same patch id. If two commits have the same Patch ID, it is almost guaranteed that they are equivalent - you will virtually never get a false positive via the patch id. False negatives occur frequently though. Any time you do git cherry-pick and have to manually resolve merge-conflicts you probably introduced differences in the changeset. Even a 1 character change will cause a different patch id to be generated.

Checking patch ID requires scripting as Chronial advises. First calculate the patch id of the Original Commit with something like

(note - scripts not tested, should be reasonably close to working though)

origCommitPatchId=$(git diff ORIG_COMMIT^! | git patch-id | awk '{print $1}')

Now you are going to have to search through all the other commits in your history and calculate the Patch IDs for them, and see if any of them are the same.

for rev in $(git rev-list --all)
do
   testPatchId=$(git diff ${rev}^1..${rev} | git patch-id | awk '{print $1}')
   if [ "${origCommitPatchId}" = "${testPatchId}" ]; then
      echo "${rev}"
   fi
done

Now you have the list of SHAs, and you can pass those to git branch -a --contains

What if the above doesn't work for you though, because of merge conflicts?

Well, there are a few other things you can try. Typically when you cherry-pick a commit the original author name, email, and date fields in the commit are preserved. So you will get a new commit, but the authorship information will be identical.

So you could get this info from your original commit with

git log -1 --pretty="%an %ae %ad" ORIG_COMMIT

Then as before you would have to go through every commit in your history, print that same information out and compare. That might give you some additional matches.

You could also use git log --grep=ORIG_COMMIT which would find any commits that references the ORIG_COMMIT in the commit message.

If none of those work you could attempt to look for a particular line that was introduced with the pickaxe, or could git log --grep for something else that might have been unique in the commit message.

If this all sounds complicated, well, it is. That's why I tell people to avoid using cherry-pick whenever possible. git branch --contains is incredibly valuable and easy to use and 100% reliable. None of the other solutions even come close.

这篇关于如何列出包含等效提交的分支的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆