使用git rev-list排除分支,但保留包含分支的共同祖先

时间:2014-01-07 18:44:27

标签: git version-control

说我有以下git repo:

--all

我想指定所有分支(--all)的git rev-list,但不包括给定分支(比如feature-D),但我想 show common feature-D的祖先和其他分支,即提交Initial1

如果我尝试git rev-list --all ^feature-D提交Initial并且1被排除在外:

--all ^feature-D

当然,我可以明确列出除feature-D之外的所有分支(git rev-list feature-A feature-B feature-C)以获得我想要的内容:

feature-A feature-B feature-C

但是有没有办法指定一个获取先前结果的转录列表,只能通过引用feature-D

(请注意,这个问题的灵感来自这个答案:https://stackoverflow.com/a/20978568/430128

2 个答案:

答案 0 :(得分:2)

这有点间接,但似乎有效。我们从:

开始
git rev-list --no-walk --all ^feature-D

生成任何ref直接指向的所有SHA-1的列表(包括标签,分支,stashes等;如果只需要分支,则使用--branches而不是--all 除了 feature-D下的那些:

$ git log --oneline --decorate --graph --all
* 74e0d3e (feature-D) 7
* 0448a13 6
| * ab3a532 (feature-C) 5
|/  
| * 50477c7 (feature-B) 4
| * 28717e5 3
|/  
* 2ac5cef (HEAD, master, feature-A) 2
* c6a10b4 1
* 76c511f Initial
$ git rev-list --no-walk --all ^feature-D
ab3a5320e792e945b896634d667df5ace4a8b871
50477c7b28b5479587e45fe97292e71a3c0851c5
28717e5628ad111e8b68323dc485fd190a780446

现在我们再次将其提供给git rev-list 以获取历史记录:

$ git rev-list --no-walk --all ^feature-D | git rev-list --stdin
ab3a5320e792e945b896634d667df5ace4a8b871
50477c7b28b5479587e45fe97292e71a3c0851c5
28717e5628ad111e8b68323dc485fd190a780446
2ac5cefb971c7f5c5be33a77a6db71127982eaf5
c6a10b4568136d65b31b7e262ef7745db4962460
76c511fcf38076e0ea98db73a4923de6fc806b4a

管道到git log --oneline --decorate --graph --stdin以验证那些是正确的提交,如果眼球不够明确:

* ab3a532 (feature-C) 5
| * 50477c7 (feature-B) 4
| * 28717e5 3
|/  
* 2ac5cef (HEAD, master, feature-A) 2
* c6a10b4 1
* 76c511f Initial

(并注意:如果使用git log --oneline --decorate --graph查看中间版本,即git rev-list --all ^feature-D,则需要添加--boundary以查看提交2; gitk可能会添加{{1}使它显示出来,而不是我测试过它。)

这里有一个缺陷:如果--boundaryfeature-C分支不存在,您将看不到提交2到初始。我不确定,但我认为唯一真正解决的问题是使用更复杂的东西。


编辑:好的,不是 更复杂。从feature-B开始打印分支。管道git for-each-ref以消除grep -v ^feature-D$。现在,您拥有所需的所有分支作为参数:

feature-D

答案 1 :(得分:1)

简单解决方案

我们可以使用正则表达式来包含--all引用和--exclude特定的分支,而不是明确地列出所有分支(手动或使用复杂的程序)。

根据手册页,--all标志将

  

假设refs/中的所有引用都在命令行中列为<commit>

理想情况下,我们会假装refs/ 中除feature-D 之外的所有引用都在命令行中列为<commit>

为了排除feature-D,我们可以使用--exclude=refs/heads/feature-D --all

注意:标记顺序很重要。

gitk用户的注释:

(可能相关,因为OP图像包含gitk屏幕截图。)

我最初在尝试忽略gitk中的分支时遇到了这个问题,我注意到上面的答案会触发一个小gitk错误。如果使用上面的标志启动gitk,那么一切正常。但是,如果在启动gitk之后从GUI菜单中修改了视图,则标志排序似乎会发生变化并导致分支重新出现。 (即使没有进行实际更改,如果按下确定按钮也会发生这种情况。)我仍然无法弄清楚在使用--all标志时如何解决这个问题,但我有一个解决方法。

我们可以使用--all

,而不是使用--branches=* --tags=* --remotes=* stash

为了排除feature-D,我们可以将其修改为--exclude=refs/heads/feature-D --branches=* --tags=* --remotes=* stash

然后我们可以使用gitk --exclude=refs/heads/feature-D --branches=* --tags=* --remotes=* stash启动gitk并通过GUI编辑视图不再导致此错误。