获取给定提交的所有子项的列表

时间:2010-04-10 15:52:22

标签: git

我想对给定提交的所有子项运行git filter-branch。这似乎不是一件容易的事,因为似乎没有办法告诉git rev-list只返回特定提交的子节点。使用..语法将不起作用,因为它还将包括该范围内任何合并的父提交。我在这里错过了什么吗?

修改

澄清一下:我有一个名为base的分支,它已多次合并到derivative。我想列出,并最终运行filter-branch,只是从最近的提交下降的提交。我还想在其他分支上列出类似的提交。

(简化)情况(derivative是左边的分支):

$ git rev-list --graph --oneline base derivative
*   f16fd151b374b2aeec8b9247489c518a6347d001 merged in the latest from the base branch
|\
| * 564d795afb63eab4ffe758dbcd726ca8b790f9f6 spelling correction
* |   2f2ed5f1d429492e1491740e30be5a58ec20af21 snogg before flarg
|\ \
| |/
| * 0c520ea33ef57b30846b122781d41fcef5e62f9b now with added flarg
* | 5068c34c3862856f511b6b4d48f2adb766e1bde4 now with added snogg
|/
* b51f227e931f830cbda042bc372087398ae7e50d initial commit

@ araqnid的建议似乎不起作用,除非我拙劣阅读它:

$ git rev-list --oneline derivative --not base
f16fd151b374b2aeec8b9247489c518a6347d001 merged in the latest from the base branch
2f2ed5f1d429492e1491740e30be5a58ec20af21 snogg before flarg
5068c34c3862856f511b6b4d48f2adb766e1bde4 now with added snogg

因为除了derivative中的提交之外,它会在base中提交所有提交。这种做法是有道理的,因为它所做的就是删除否定提交的祖先。我希望它展示的只是第一行。

4 个答案:

答案 0 :(得分:5)

好吧,“ - 分支”或“--all”将包括所有分支提示,然后“ - not A”将排除A及其所有祖先。但是,“ - 分支 - 不是A”将包括不包含A的分支,我认为这不是您需要的分支。

虽然你可以解决问题,但没有简单的方法来获得你想要的一切。这将列出包含提交A:

的所有分支
git for-each-ref refs/heads/* | while read rev type name; do
  git rev-list $rev | grep $(git rev-parse A) >/dev/null && echo $rev
done

然后你需要列出所有可以从这些修订中获得的修订,但不能列出A本身和任何修订版本

git rev-list $(git for-each-ref refs/heads/* | while read rev type name; do
      git rev-list $rev | grep $(git rev-parse A) >/dev/null && echo $rev
    done) --not A

请注意,我只是给出了一个非常简短的测试:p但我认为基本面是合理的。

答案 1 :(得分:5)

显示从其他一组提交A的祖先路径:

  

git log --ancestry-path ^A others

显示回购中的所有无法访问的提交:

  

git fsck --unreachable --no-reflogs \
  | awk '$2 == "commit" {print $3}'

在回购中的任何位置跟踪提交A的所有后代:

git log --ancestry-path --graph --decorate --oneline ^A \
   --all $(git fsck --unreachable --no-reflogs | awk '$2=="commit" {print $3}')

显示其历史记录包含提交的所有引用:

git log --ancestry-path --graph --simplify-by-decoration --oneline --all ^A
# and in case A might have a direct ref, add:
git log --ancestry-path --graph --simplify-by-decoration --oneline A^!

编辑:更正:当A本身的父母与其他孩子在一起时,不要显示不需要的提交。

答案 2 :(得分:1)

我做了另一个版本。我不知道它是好还是坏。

getGitChildren(){
    git rev-list --all --parents | grep "^.\{40\}.*${1}.*" | awk '{print $1}' | xargs -I commit git log -1 --oneline commit | cat -
}

这样使用:

$ getGitChildren 2e9df93
f210105376 feat(something): did that feature
9a1632ca04 fix(dummy): fix something

它只是提供了一个提交的直接子列表。

答案 3 :(得分:0)

这似乎是这样做的:

$ for rev in $(git rev-list --branches); do
    git rev-list $rev \
      | grep $(git rev-parse base) &>/dev/null \
    && echo $rev;
  done \
  | xargs -L 1 git rev-list -n 1 --oneline
f16fd151b374b2aeec8b9247489c518a6347d001 merged in the latest from the base branch
564d795afb63eab4ffe758dbcd726ca8b790f9f6 spelling correction

xargs的最后一个管道部分只是为了显示每个提交的提交消息。

这列出了除了子节点之外的目标提交,这实际上就是我想要的。虽然它的速度相当缓慢:在40次提交的回购中运行需要3秒钟。这并不令人惊讶,因为它和安德烈巨人一样蛮力。我想一个更优雅的方法将遍历每个ref的rev-list,并构建一个链接到其子节点的每个提交的哈希树,然后从目标提交开始。但那有点复杂,所以我希望有一个git命令:)

我仍然需要弄清楚如何将这组提交转换为filter-branch。我想我可以从rev-list命令中查看$GIT_COMMIT的{​​{1}}。