查找 git 分支的提交,这些提交没有被挑选到另一个分支中

k_r*_*rus 7 git cherry-pick

我在git有两个分支,其中一个分支master包含所有提交,另一个分支,例如,release包含来自第一个分支的一些精选提交master。由于提交是在 中精心挑选的release,因此它们具有与 中相应提交不同的提交哈希值master,但提交消息是相同的。

现在我想找到来自 的提交master,这些提交没有被精心挑选到 中release。请注意,由于冲突解决方案,精选提交的代码可能与原始提交不同。我该怎么做?git对此有本机支持吗?

例子:

master分支:

git checkout master
git log --oneline -7
Run Code Online (Sandbox Code Playgroud)

给出

2cba4b1d (HEAD -> master) Message subject for commit 7
f54fc16f Message subject for commit 6
4d871cbd Message subject for commit 5
a83ed44c Message subject for commit 4
48d0fb73 Message subject for commit 3
931da9a6 Message subject for commit 2
8553323b Message subject for commit 1
Run Code Online (Sandbox Code Playgroud)

release分支

2cba4b1d (HEAD -> master) Message subject for commit 7
f54fc16f Message subject for commit 6
4d871cbd Message subject for commit 5
a83ed44c Message subject for commit 4
48d0fb73 Message subject for commit 3
931da9a6 Message subject for commit 2
8553323b Message subject for commit 1
Run Code Online (Sandbox Code Playgroud)

给出

d65a04c6 (HEAD -> release) Message subject for commit 7
8aeecd92 Message subject for commit 6
2a54e335 Message subject for commit 4
99985f38 Message subject for commit 3
e76a9bb4 Message subject for commit 1
Run Code Online (Sandbox Code Playgroud)

因此,两个分支之间的差异将是带有消息主题的两次提交:

Message subject for commit 5
Message subject for commit 2
Run Code Online (Sandbox Code Playgroud)

如果显示提交哈希值也没关系:

4d871cbd Message subject for commit 5
931da9a6 Message subject for commit 2
Run Code Online (Sandbox Code Playgroud)

附加说明和要求:

上面的示例以与合并提交相同的顺序返回差异。在结果中获得与原始提交日志中相同的顺序有助于识别 的原始提交日志中的提交master。如果也能实现就好了。

就我而言,两个分支都有线性历史并且没有合并提交。

Mar*_*ara 5

您的问题与我几个月前读到的关于识别重新调整提交的方法的另一个问题非常相似。与 with 一样rebasecherry-picking 的作用是提取一次提交中所做的更改并将其应用到另一个提交中。这些命令都不会跟踪原始提交,git 不需要区分“副本”,主要是因为它们可能会产生冲突,并且生成的提交会有所不同,如您所知。

\n

幸运的是,git 为我们提供了精选提交的巨大帮助:选项--cherry-pick。我邀请您阅读整个描述(大约--left/right-only),但这是有趣的部分:

\n
\n

当提交集受到对称差异的限制时,忽略与另一侧\xe2\x80\x9d 上的另一个提交引入相同更改的任何提交。

\n
\n

看起来很有希望,对吧?不,问题是:与另一个提交相同的更改。如果冲突解决后精选的提交有所不同怎么办?Git 无法将其标记为“cherry-picked”,因为它们不再是补丁等效的,并且此选项还不够。从最简单的情况(这不是你的情况)开始,所有精心挑选的提交都已成功应用于另一个分支,你可以用以下方法解决:

\n
git log --format="%h %s" --cherry-pick --oneline --left-only --no-merges master...release \n
Run Code Online (Sandbox Code Playgroud)\n

文档中对此进行了很好的解释,除了对称差异的概念之外,总之,它需要所有master未成功挑选的提交release

\n

正如我所说,它并不完美,但至少我们有一个好的起点:现在我们只需要从这个列表中删除所有提交消息与分支中另一个提交的提交消息相对应的提交release,找到精心挑选的产生冲突的提交。这是您唯一可以做的检查,不包括重新记录。

\n

这是脚本(未完全测试):

\n
git log --format="%h %s" --cherry-pick --oneline --left-only --no-merges master...release |\nwhile read cmt_log \ndo\n    cmt_msg=`echo "${cmt_log}" | awk \'{ $1=""; print }\'`\n    git log --format=" %s" master..release | grep --fixed-string -s "${cmt_msg}" > /dev/null || echo ${cmt_log}\ndone\n
Run Code Online (Sandbox Code Playgroud)\n

基本上,从%h %s字符串中我只保存 subject( %s) ,然后用它来grep查找匹配项(如果存在),否则我将其打印在标准输出上。我--fixed-stringgrep选项中指定只是为了确保提交消息不会被解释为正则表达式,例如匹配不应该匹配的内容。

\n