我想要找到重复更改的方法。 patch-id可能是相同的,但提交属性可能不是。
这似乎是patch-id的预期用途:
git patch-id --help
IOW,你可以用这个东西来寻找可能的重复提交。
我想把“git log”,“git patch-id”和uniq串在一起 可以做得很糟糕,但如果有人有一个命令,那么 工作得很好,我很感激。
答案 0 :(得分:11)
由于重复更改可能不在同一分支上(除非它们之间存在还原),您可以使用git cherry:
git cherry [-v] [<upstream> [<head> [<limit>]]]
upstream
将成为head
中检查重复更改的分支。
答案 1 :(得分:9)
为了查找特定提交的重复项,这可能对您有用。
首先,确定目标提交的补丁ID:
$ THE_COMMIT_REF_OR_SHA_YOURE_SEEKING_DUPES_OF='7a3e67c'
$ git show $THE_COMMIT_REF_OR_SHA_YOURE_SEEKING_DUPES_OF | git patch-id
f6ea51cd6acd30cd627ce1a56e2733c1777d5b52 7a3e67ce38dbef471889d9f706b9161da7dc5cf3
第一个SHA是patch-id。接下来,列出每个提交的补丁ID并过滤掉任何匹配:
$ for c in $(git rev-list --all); do git show $c | git patch-id; done | grep 'f6ea51cd6acd30cd627ce1a56e2733c1777d5b52'
f6ea51cd6acd30cd627ce1a56e2733c1777d5b52 5028e2b5500bd5f4637531e337e17b73f5d0c0b1
f6ea51cd6acd30cd627ce1a56e2733c1777d5b52 7a3e67ce38dbef471889d9f706b9161da7dc5cf3
f6ea51cd6acd30cd627ce1a56e2733c1777d5b52 929c66b5783a0127a7689020d70d398f095b9e00
所有这些,一些额外的标志,以及utility script:
的形式test ! -z "$1" && TARGET_COMMIT_SHA="$1" || TARGET_COMMIT_SHA="HEAD"
TARGET_COMMIT_PATCHID=$(
git show --patch-with-raw "$TARGET_COMMIT_SHA" |
git patch-id |
cut -d' ' -f1
)
MATCHING_COMMIT_SHAS=$(
for c in $(git rev-list --all); do
git show --patch-with-raw "$c" |
git patch-id
done |
fgrep "$TARGET_COMMIT_PATCHID" |
cut -d' ' -f2
)
echo "$MATCHING_COMMIT_SHAS"
用法:
$ git list-dupe-commits 7a3e67c
5028e2b5500bd5f4637531e337e17b73f5d0c0b1
7a3e67ce38dbef471889d9f706b9161da7dc5cf3
929c66b5783a0127a7689020d70d398f095b9e00
它并不是非常快速,但是对于大多数repos来说应该完成工作(对于一个拥有826次提交的repo只测量36秒,在2.4GHz Core 2 Duo上测量158MB .git目录)
答案 2 :(得分:3)
我有一个适用于玩具回购的草稿,但它保留了 patch-&gt;在内存中提交映射,它可能在大型存储库上有问题:
# print commit pairs with the same patch-id
for c in $(git rev-list HEAD); do \
git show $c | git patch-id; done \
| perl -anle '($p,$c)=@F;print "$c $s{$p}" if $s{$p};$s{$p}=$c'
输出应该是具有相同patch-id的提交对 (3个副本A B C表示为“A B”,然后是“B C”)。
更改git rev-list命令以限制检查的提交:
git log --format=%H HEAD somefile
追加“| xargs git show”以详细查看提交, 或“| xargs git show -s --oneline”获取摘要:
0569473 add 6-8
5e56314 add 6-8 again
bece3c3 comment
e037ed6 add comment again
事实证明,patch-id在我原来的情况下不起作用 后来的提交还有其他变化。 “git log -S”更有用。
答案 3 :(得分:2)
bsb建议的漂亮命令需要进行一些小的调整:
(1)命令应该使用
而不是运行git show
的{{1}}。
git diff-tree --cc
否则 git diff-tree -p
会生成虚假的空SHA1哈希值。
(2)当使用git patch-id
管道时,xargs
应该有xargs
参数。否则,三重提交将不会与等效提交配对。
这是-L 1
中的别名:
~/.gitconfig
答案 4 :(得分:1)
要搜索提交$hash
的重复提交,请排除合并提交:
git rev-list --no-merges --all | xargs -r git show | git patch-id \
| grep ^$(git show $hash|git patch-id|cut -c1-40) | cut -c42-80 \
| xargs -r git show -s --oneline
要搜索合并提交$mergehash
的副本,请将$(git show $hash|git patch-id|cut -c1-40)
替换为git diff-tree -m -p $mergehash | git patch-id
给出的两个修补程序ID(第1列)之一。它们与其两个父项中的每一个对应于合并提交的差异。
要查找所有提交的重复项,请排除合并提交:
git rev-list --no-merges --all | xargs -r git show | git patch-id \
| sort | uniq -w40 -D | cut -c42-80 \
| xargs -r git log --no-walk --pretty=format:"%h %ad %an (%cn) %s" --date-order --date=iso
可以通过将参数更改为git rev-list
来扩展或限制对重复提交的搜索,--all
接受多个选项。例如,要将搜索限制为特定分支,请指定其名称而不是选项HEAD ^HEAD~100
;或者在最近的100次提交中搜索传递参数--no-merges
。
请注意,这些命令很快,因为它们不使用shell循环和批处理进程提交。
要包含合并提交,请移除选项xargs -r git show
,然后将xargs -r -L1 git diff-tree -m -p
替换为git diff-tree
。这个速度要慢得多,因为每次提交都会执行{{1}}次。
说明:
第一行生成带有提交哈希的修补程序ID的映射(2列数据,每个40个字符)。
第二行仅保留与重复的修补程序ID(第1列)对应的提交哈希值(第2列)。
最后一行打印有关重复提交的自定义信息。
答案 5 :(得分:0)
对于任何想在Windows powershell上执行此操作的人,unagi的答案的等效命令是:
git rev-list --no-merges --all | %{&git.exe show $_} |
git patch-id | ConvertFrom-String -PropertyNames PatchId, Commit |
Group-Object PatchId | Where-Object count -gt 1 |
%{$_.group.Commit + " "}
给出如下输出:
1605e0e1e13d7b3f456c20432d8edec664ca7117
1e8efa8f2f01962a2c08fd25caf687d330383428
b45b6db084b27ae420ac8e9cf6511110ebb46513
4a2e1e3ba5a9a1d5db1d00343813e1404f6124e2
将重复的提交哈希分组在一起。
注意:在我的仓库中,这是一个缓慢的命令,因此请确保适当地过滤对rev-list的调用!
答案 6 :(得分:0)
确保使用最新版本的Git
OP bsb的answer中提到的diff_flush_patch_id()
并不总是唯一的。
这是因为,在Git 2.29(2020年第四季度)之前,patch-id计算并未忽略空格等“不完整的最后一行”标记。
请参见commit 82a6201的René Scharfe (rscharfe
)(2020年8月19日)。
(由Junio C Hamano -- gitster
--在commit 5122614中合并,2020年8月24日)
patch-id
:忽略1-2000
中文件末尾的换行符报告人:蒂尔曼·沃格尔
初始测试者:蒂尔曼·沃格尔
签名人:RenéScharfe
计算补丁程序ID时将忽略空格。
这是通过在对diff行进行散列之前将所有空格删除(包括文件末尾的换行符)来除去的。
但是,如果缺少该换行符,diff将在单独的行中报告该事实,该行包含“ \\文件末尾没有换行符\ n”,并且此标记像上下文行一样散列。这违背了使补丁ID与空白无关的目标。
使用与2485eab55cc ({{3}中添加的
git patch-id
(git-patch-id:不要跳过“ no newline”标记,2011-02-17)相同的启发式方法}})而是跳过以反斜杠和空格开头且长度超过十二个字符的差异行。