我有一个有两个分支的线性历史记录,dev
和master
。 master
总是可以快进dev
,而且没有其他分支。我想从dev
获取master
和git rev-parse
之间的所有提交。
例如,我的历史记录如下(来自git log --graph --decorate --oneline --branches
):
* 693dc30 (HEAD, dev) E
* d650d35 D
* 1c4e641 C
* b27ea83 (master) B
* 95fe748 A
...
我目前正在尝试致电
git rev-parse master..dev
并希望得到像
这样的东西693dc30...
d650d35...
1c4e641...
相反,我得到
693dc30...
b27ea83...
^b27ea83...
如何获取指定选择之间的完整提交列表,以及如何正确解释我得到的git rev-parse
的结果?
我使用的是Git 1.7.1版。我更喜欢在这个应用程序中使用像rev-parse
这样的低级命令,而不是log
之类的瓷器,但我对任何运行良好的解决方案持开放态度。
答案 0 :(得分:4)
作为Leon noted in a comment,答案是使用git rev-list
。
Git的修订处理代码很复杂。但是你可以使用一个很好的心理模型:
修订说明符,列在the gitrevisions
documentation中。除了范围符号(X..Y
和X...Y
以及一些更深奥的说明符(如<rev>^@
)之外,这些符号指定了一个特定的对象,通常是提交。指向带注释标记的标记名称解析为其带注释标记的对象,但除非使用gitrevisions
样式后缀强制Git将这些标记“剥离”为提交,或者甚至是树木或斑点。
rev-parse
命令适用于修订说明符(加上所有其他好东西),例如解析shell脚本的参数,或显示顶级目录的位置,或测试{{1} } repository)。
但是我可以选择其中一个“带有祖先”,我称之为。这只适用于提交,或者Git可以解析为提交的标记对象。选择带有祖先的提交会获得提交,并且其父提交(通常只提交一次,但如果是合并则提交更多),并且那些父提交'父级 - 提交的祖父母 - 和他们的父母等等永远在线,直到你遇到根提交的死胡同(没有父母的提交)。
--bare
命令是选择与祖先的关系。实际上,除非您向参数添加rev-list
,否则始终会执行此操作。
当您使用--no-walk
或X..Y
等范围说明符时,如果需要,X...Y
会尽力将其转换为大致相等的单个提交,前缀为git rev-parse
。这实际上丢失了一些信息:你无法从^
真正告诉X...Y
,例如, 1 这意味着你无法确定哪个是左边的 - 侧修订说明符。但总的来说,如果你正在做一些需要X Y ^$(git merge-base X Y)
- 样式解析的东西,你只需要使用rev-list
而不必担心;并且git rev-list
还有更多标记,例如git rev-list
的前缀-
。
(--boundary
命令也能够公开树和对象ID,但是你必须给它额外的标志来实现它。很多Git命令都使用它git rev-list
's documentation非常长并且充满了rev-list
之类的特定选项。但要实现的一个有用的事情是,--bisect
和git log
几乎是相同的命令,具有不同的默认输出格式。其他微妙的差异,但他们使用相同的源代码来完成相同的事情,并且两个前端是从单个git rev-list
文件构建的。)
1 大多数命令不需要,但builtin/log.c
本身,git rev-list
。此外,如果有多个合并基础,git diff
将重新解析为 X 的ID(无帽子前缀)加上 Y 的ID(无帽子)前缀)加上所有合并库的ID(全部带帽子前缀),因为这里的想法是选择从 X 或 Y可以到达的所有提交,但不是两者兼而有之,因此排除了所有合并基础和所有早期提交。