Git 如何列出包含等效提交的分支

Git 如何列出包含等效提交的分支,git,version-control,Git,Version Control,在前面的一个问题中,有人提供了一个关于查找包含确切提交的分支的答案: 接受的答案强调了这只适用于精确的提交id,而不适用于相同的提交。有人进一步指出,Git Cherry可用于解决这一问题 Git cherry似乎正处于相反的方向;查找提交没有被推到上游。如果我不知道是哪个分支创建了它,以及上游是什么,这是没有用的。所以我看不出这对解决这个问题有什么帮助 是否有人可以解释/提供一个示例,说明如何使用git cherry查找包含特定提交的“等效”的所有分支?在回答哪些分支包含等效提交的问题之前,

在前面的一个问题中,有人提供了一个关于查找包含确切提交的分支的答案:

接受的答案强调了这只适用于精确的提交id,而不适用于相同的提交。有人进一步指出,Git Cherry可用于解决这一问题

Git cherry似乎正处于相反的方向;查找提交没有被推到上游。如果我不知道是哪个分支创建了它,以及上游是什么,这是没有用的。所以我看不出这对解决这个问题有什么帮助


是否有人可以解释/提供一个示例,说明如何使用git cherry查找包含特定提交的“等效”的所有分支?

在回答哪些分支包含等效提交的问题之前,您必须确定“哪些提交是等效的”。一旦有了它,只需在每个提交上使用
git分支--contains

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

最可靠的方法是检查提交引入的变更集的补丁id。这就是
git cherry
git log--cherry
git log--cherry mark
所依赖的。在内部,它们都调用
git补丁id
。补丁id只是规范化的变化差异的SHA1。任何引入相同更改的提交都将具有相同的修补程序id。此外,任何引入几乎相同的更改的提交(仅在空格或它们在文件中应用的行号上不同)都将具有相同的修补程序id。如果两个提交具有相同的修补程序id,几乎可以保证它们是等效的-通过补丁id,你几乎永远不会得到假阳性。尽管假阴性经常发生。任何时候,如果您执行了
git cherry pick
,并且必须手动解决合并冲突,则可能会在变更集中引入差异。即使更改1个字符,也会生成不同的修补程序id

检查补丁ID需要按照Chronial的建议编写脚本。首先计算原始提交的补丁id,如下所示

(注意-未测试的脚本应合理接近工作状态)

现在,您必须搜索历史记录中的所有其他提交,计算它们的补丁ID,并查看其中是否有相同的补丁ID

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
现在您有了SHA列表,您可以将它们传递给
git branch-a--contains

但是,如果由于合并冲突,上述方法对您不起作用,该怎么办

嗯,你还可以尝试其他一些事情。通常,在选择提交时,会保留提交中的原始作者姓名、电子邮件和日期字段。因此,您将获得一个新的提交,但作者信息将是相同的

因此,您可以使用从原始提交中获取此信息

git log -1 --pretty="%an %ae %ad" ORIG_COMMIT
然后像以前一样,您必须检查历史记录中的每个提交,打印出相同的信息并进行比较。这可能会给你一些额外的匹配

您还可以使用git log--grep=ORIG_COMMIT在提交消息中查找引用ORIG_COMMIT的任何提交

如果这些都不起作用,您可以尝试查找鹤嘴锄引入的特定行,或者
git log--grep
查找提交消息中可能唯一的其他行


如果这一切听起来很复杂,那么,的确如此。这就是为什么我告诉人们尽可能避免使用樱桃采摘<代码>git分支--包含非常有价值,易于使用,而且100%可靠。其他的解决方案都无法接近。

以下方法似乎有效(但没有经过太多测试)。它运行
git cherry
,如果
git cherry
没有将提交列为缺少分支,则打印分支名称

#用法:git cherry包含[refs]
#打印包含等效提交的每个本地分支。
git-cherry-contains(){
本地sha;sha=$(git rev parse--verify“$1”)| |返回1
本地引用;引用=${2:-refs/heads/}
地方分行
当IFS=读取-r分支时;执行
如果!git cherry“$branch”$sha“$sha^”| grep-qE“^\+$sha”;那么
回显“$分支”
fi
完成<命令
使用以下Bash命令(用正在搜索的提交哈希替换
):

描述 计算给定GIT修订参数的修补程序ID(例如提交的哈希值)。然后使用计算出的修补程序ID查找所有提交。最后,包含这些提交的所有分支名称都打印到控制台


当然,这只适用于所有补丁ID相同的情况(cherry picked)提交。任何时候您选择并必须手动解决合并冲突时,您可能会在变更集中引入差异。这将导致不同的修补程序id。

我建议编写一个脚本,使用
git rev list
git PATCH id
来确定这一点。您可能还需要解析注释
git cherry pick
在提交消息中留下的on,作为补丁id(也是
git cherry
的基础)不是十全十美的,如果你解决了任何冲突,它就会崩溃。我不是故意+1那句话:我不知道你说了什么,也不知道这对我有什么帮助。我应该用它们来生成一个列表吗?假设有人解决了冲突,而我的队友不够聪明,不能使用cherrypick-x,因为我必须向他们指出。那么,你就完蛋了ed.如果你想确切地知道哪些分支包含哪些提交,只使用合并,而不使用cherry pick。你可以假设具有相同提交消息的提交可能是相同的,并在它们的差异上进行一些有趣的启发式来验证该假设。但该过程很容易出错,你必须自己编写代码。听起来像li把pos机打开
git log -1 --pretty="%an %ae %ad" ORIG_COMMIT
$ for i in `git rev-list --all --grep="something unique in the commit message"`; do git branch --all --contains $i; done | sort | uniq
PATCH_ID=$(git show <COMMIT HASH> | git patch-id | cut -d' ' -f1) \
&& ALL_MATCHING_COMMIT_HASHES=$(git log --all -p | git patch-id | grep $PATCH_ID | cut -d' ' -f2) \
&& for HASH in $ALL_MATCHING_COMMIT_HASHES; do echo "$(git branch -a --contains $HASH) (commit $HASH)"; done 
user@host test_cherry_picking $ PATCH_ID=$(git show 59faabb91cfc8e449737f93be8c7df3825491674 | git patch-id | cut -d' ' -f1) \
&& ALL_MATCHING_COMMIT_HASHES=$(git log --all -p | git patch-id | grep $PATCH_ID | cut -d' ' -f2) \
&& for HASH in $ALL_MATCHING_COMMIT_HASHES; do echo "$(git branch -a --contains $HASH) (commit $HASH)"; done

* hotfix (commit 59faabb91cfc8e449737f93be8c7df3825491674)
master (commit bb5fa0d16931fa1d5fa9f5e9ee5c27634fad7da8)

user@host test_cherry_picking $