列出分支中的所有提交,直到标记(包括)

时间:2019-05-08 23:46:09

标签: git bitbucket

在一个分支中,我在4个不同的单独提交中添加了4个文件。每个提交都有一个文件。下面是示例提交消息

例如:

  Adding file 1 
  Adding file 2  ---test-tag
  Adding file 3
  Adding file 4

我用名为“ test-tag”的标签标记了第二次提交。我想列出该分支中所有的提交,从标记(包括包含该标记的提交)到分支中的最新提交。提交列表也应包括已标记的提交。使用下面的提交,我将从标记中获得提交,但不包括它。

git log --pretty=oneline test-tag..

1 个答案:

答案 0 :(得分:0)

对于大多数Git命令,两点..表示不包括左侧命名的提交,如您所见。 (所有提交的枚举均从右侧命名的提交开始,省略名称意味着“当前提交”,也就是HEAD@。)因此,有两种方法可以解决此问题:

  • 在此提交之前 开始提交,或者
  • 使用一个标志告诉命令我希望通常会被排除的提交

后者似乎更简单,并且实际上在大多数情况下都可以正常工作

git log --boundary --pretty=oneline test-tag..

但是,--boundary在某些更复杂的情况下表现较差,因此我更喜欢从提交的父项开始排除。

使用后缀^或后缀~表示法,很容易找到任何提交的第一个父级:

git log --pretty=oneline test-tag^..
git log --pretty=oneline test-tag~..

对于这种特殊情况,两者都可以做您想要的,但是它们也有轻微的缺陷。尽管存在一些轻微的缺陷,您可能还是想熟悉此符号,因为它非常方便。后缀代字号表示一个可选数字(默认为1),并且会计算出这么多的第一祖父母。

您没有显示四个提交的实际提交哈希ID,所以让我使用自己的随机旧存储库:

$ git log --oneline -n 4
11ae6ca (HEAD -> master) add run-checks script
d1574b8 mxgroup.py: sort-of-mutual-exclusive-groups
b9491ea gerrit-review.sh: push to refs/for/
676699a wacky.py - replacing class-member functions

这些提交都没有被标记,因此让我们从HEAD / master / @开始倒数:

  • @~1表示提交d1574b8,后退
  • @~2意味着提交b9491ea,后退两步
  • @~3表示提交676699a,后退三步

以此类推。

更多细节(准备就绪时可以阅读,上面的内容足够用于一段时间)

帽子或插入符号(^)后缀也可以带有数字,但这仅在所涉及的提交是 merge commit 时才有意义。合并提交是指具有个以上父级的任何提交,通常是两个使用git merge来合并两个分支的提交:

          I--J   <-- branch1
         /
...--G--H
         \
          K--L   <-- branch2

在这里,名称branch1branch2分别表示提交JL。 (这里JL代表实际的大丑陋哈希ID。)

假设我们先运行git checkout branch1,然后运行git merge branch2。 Git将从两个分支提示提交向后走,第一步分别到IK,然后再从两个步骤到H。提交H在两个分支上,并且是两个分支技巧之前的最佳共享提交,因此它是合并操作的合并基础。

Git然后将提交H中的所有文件与提交J中的所有文件进行比较,以查看某人在branch1上所做的工作。另外,Git将H中的所有文件与L中的所有文件进行比较,以查看某人对branch2所做的工作。然后,合并操作合并这些更改,将合并的更改应用于H中的文件。如果一切顺利,Git将使用应用了两组套变更的文件(即,已合并了两条开发线)进行新的提交。新的提交如下所示:

          I--J
         /    \
...--G--H      M   <-- ??? (what name points to M?)
         \    /
          K--L

新提交M获得一个新的哈希ID,该ID与每个现有和将来的提交都不同。现在必须更新 Some 分支名称,以记住新的提交M。更新后的实际分支名称取决于您执行的是git checkout branch1; git merge branch2还是git checkout branch2; git merge branch1。无论您签出的哪个分支,那个名称都会被移动,而另一个保留。上面我们说过,我们假设您执行了git checkout branch1,所以我们将名称branch1移到新的提交M

          I--J
         /    \
...--G--H      M   <-- branch1
         \    /
          K--L   <-- branch2

由于新的提交M记住了两次以前的提交,而不仅仅是一次,因此我们现在遇到了一些有趣的情况。两者之一是M第一个父项:在这种情况下,提交J是因为名称branch1曾经指向J 1 因此,M~1M^1表示提交JM的两个父对象的 first 。 / p>

要查找提交{{1}的父级 second 的提交L,则不能使用后缀M。您必须改用~后缀,并写成^。这告诉Git:找到提交M,然后找到其第二父级。

因此,这是M^2后缀比^后缀更有用的地方。否则,后缀~比后缀~更有用,因为您可以倒数。不过请注意,您可以组合后缀:~使您提交M^2,而L使您成为M^2~的父项LK让您成为M^2~2的父母K,也可以通过使用H或仅仅使用M^1~2来达到:M~3然后返回三个步骤,只要有选择就使用第一位父母。


1 如果相反进行合并,则M指向branch2,它的第一个父级是M,第二个父级是L。除了哪个父节点是第一父节点和哪个分支名称发生更改之外,合并过程通常是完全对称的。


包括带有两点符号的合并提交

假设我们现在继续进行J设置,要么记下branch1的哈希ID,要么设置一个标记为我们记住M

M

然后我们继续进行一些提交:

          I--J   ..... tag: test-merge
         /    \ .
...--G--H      M   <-- branch1
         \    /
          K--L   <-- branch2

如果我们现在想 I--J ..... tag: test-merge / \ . ...--G--H M--N--O <-- branch1 \ / K--L <-- branch2 git log包括M怎么办?我们通常的写作技巧:

O

不起作用,因为git log test-merge^.. 表示找到提交test-merge^,然后退回到其第一个父项M,并排除J(及更早版本) 。结果是您看到J:五次提交,您期望三次提交。

如果您尝试:

K-L-M-N-O

您正在告诉Git 找到提交git log test-merge^2.. ,然后退回到第二个父M,并排除L(及更早版本)。结果是您看到L:再次提交了5次。

要直观地查看,请在上方绘制图形。用红色荧光笔标记已排除提交。保持前进状态,标记所有可以通过向后工作而到达的较早提交。然后,用绿色荧光笔标记第一个 included 提交。保持绿色前进,标记所有可以通过向后工作而到达的较早的提交,但是当您到达带有红色标记的提交时就停止。

只获得您想要的三个提交的方法(除了H-I-M-N-O有时有效,但有时无效)是告诉Git:排除提交--boundary排除提交J 。您可以通过不使用两点符号来实现:

L

此处的前缀 git log ^M^1 ^M^2 HEAD 告诉Git:不是。因此,^将从git log开始并向后工作,但是排除 HEAD以及M^1

正确答案

当然,这仅是因为M^2正好有两个父母。我们将其中的 都列为“不显示此提交,也没有更早的显示”,我们得到了想要的东西。但是,如果我们选择非合并提交,则M会失败,因为没有第二亲。我们需要的是一种表示提交^<commit>^2 的所有父母的符号。

事实证明只有这样一种表示法。它(以及许多其他)在the gitrevisions documentation中列出,并且此特定字符的后缀为M。这样我们就能得到想要的东西:

^@

无论选择的提交有多少父母,此方法都有效:我们将所有 排除在外,同时保留提交本身。

(Git 2.11中也引入了一个相对较新的git log test-merge^@.. 后缀。这些文档页面值得偶尔阅读。)