我需要列出触及源树中一条路径而不是另一条路径的提交。
D - 头
C - 触及 foo 和 bar
B - 触及 foo
A - 基线
在A和DI之间想要一个包含文件夹 foo 的所有提交的列表,除非他们还触摸文件夹 bar ,换句话说,在上面的例子我希望看到B而不是C.
我试过了git rev-list A..D --exclude='bar' -- foo
,但这给了我B和C两个。
请告知。
答案 0 :(得分:2)
自Git 1.9以及介绍路径规范魔术:(exclude)
及其简短形式:!
以来,语法应为:
git rev-list A..D -- foo ":(exclude)bar"
但是,这仍然会列出C,即使为该提交显示的文件不包含其路径中包含bar
的文件:
git log --oneline --name-status A..D -- foo ":(exclude)bar"
pathspec排除有效,但仍会列出C
。
答案 1 :(得分:1)
Git没有内置任何功能。但是,使用the comm
command使用小型shell脚本构建起来很容易。只需获取影响有趣文件的所有提交的列表,以及影响使提交无趣的文件的所有提交的第二个列表,然后使用comm
提取有趣的项目(出现在第一个列表中的那些项目,但是不在第一和第二列表中。)
因此:
git rev-list A..D -- foo > /tmp/list1
git rev-list A..D -- bar > /tmp/list2
comm -23 /tmp/list[12]
请注意"已排序" comm
的要求是故意违反的(并且在此违反);如果您的特定comm
坚持,您可能需要编写自己的变体。
编辑:我在Git 2.8.1中测试了VonC的建议,创建了一个新的存储库,其中包含文件A / a和B / b的初始提交:
$ git --version
git version 2.8.1
$ git log --oneline --name-status
731a059 both
M A/a
M B/b
6894130 B only
M B/b
b4bb2d8 A only
M A/a
f134515 initial
A A/a
A B/b
正确添加-- A
会丢弃B only
提交:
$ git log --oneline --name-status -- A
731a059 both
M A/a
b4bb2d8 A only
M A/a
f134515 initial
A A/a
但是,添加:(exclude):B
对所选提交没有影响:
$ git log --oneline --name-status -- A ':(exclude):B'
731a059 both
M A/a
b4bb2d8 A only
M A/a
f134515 initial
A A/a
提交731a059
,它接触文件A / a和B / b,仍然出现在输出中,初始提交f134515
也是如此。不同之处在于,当选择也影响B / b的两个提交时,省略文件 B / b。原始问题要求排除整个提交。
编辑2(使用comm
和bash&#39; <(...)
语法,省略临时文件:
[~/tmp/git-exclude]$ comm -23 <(git rev-list HEAD -- A) <(git rev-list HEAD -- B)
b4bb2d84d633e2254081b7ce99681d92b7974a9d
这是所需的输出,因为只有提交b4bb2
仅影响 A
目录。