检测远程跟踪分支何时在Git中强制更新

时间:2016-09-25 20:46:19

标签: git

如何从脚本中检测远程跟踪分支是否已在Git中强制更新?

我可以知道本地和远程分支的哪些提交有所不同吗?

由于

1 个答案:

答案 0 :(得分:1)

  

如何从脚本中检测远程跟踪分支是否已在Git中强制更新?

git fetch输出中显而易见(实际上是stderr):

   d1a8e9c..0d12484  next       -> origin/next
 + 085c69e...636c0c5 pu         -> origin/pu  (forced update)
   5c9b3b6..9c14a42  todo       -> origin/todo

(这是通过更新Git的Git存储库)。在这种情况下,pu(取件分支)已强制更新,+(forced update)都表明了这一点。

要在事后检测到它,请使用远程的reflog:

$ git reflog origin/pu
636c0c5 refs/remotes/origin/pu@{0}: fetch: forced-update
085c69e refs/remotes/origin/pu@{1}: fetch: forced-update
eb0e753 refs/remotes/origin/pu@{2}: fetch: forced-update
7d82ce0 refs/remotes/origin/pu@{3}: fetch: forced-update
091bd8f refs/remotes/origin/pu@{4}: fetch -a origin: forced-update
... [snip]
a6f7b76 refs/remotes/origin/pu@{32}: pull --rebase: forced-update
...
ca1441a refs/remotes/origin/pu@{45}: fetch: fast-forward
a753ca6 refs/remotes/origin/pu@{46}: 
14a019f refs/remotes/origin/pu@{47}: fetch: forced-update
...

(我不知道origin/pu@{46}在这里发生了什么,但我希望包含@{45}来表明有时甚至pu分支都会快速转发。:-))

请注意,必须启用远程的reflog才能生效。这些行可能并不总是说fetch,如上例中的pull --rebase

检测这是强制更新的另一种方法是比较每个reflog。当标签从祖先移动到后代时发生快进,而当标签从一个提交移动到另一个前一个提交的提交时发生强制更新。因此:

$ git merge-base --is-ancestor origin/pu@{46} origin/pu@{45} &&
> echo fast-forward || echo forced
fast-forward
$ git merge-base --is-ancestor origin/pu@{3} origin/pu@{2} &&
> echo fast-forward || echo forced
forced

这表明从@ {46}移动到@ {45}是快进(正如在reflog中所说的那样),而从@ {3}移动到@ {2}是强制更新(因为它也是在reflog中说。像这样使用git merge-base --is-ancestor可能比在reflog更新消息中检查文字字符串更好,因为它不依赖于变幻无常的面向人的输出。

  

我可以知道本地和远程分支的哪些提交有所不同吗?

这似乎与是否有强制更新无关。 Git有一个使用三个(不是两个,但是三个)点的特殊语法,它产生对称差异

注意:为了便于说明,我将把对称差异与--left-right结合起来。出于编程目的,通常需要此选项,或--left-only--right-only或此类选项的某种组合以及--cherry-pick等其他标记。来自另一个存储库的这个特定输出不是很有趣,因为一切都在“左侧”(master分支,而不是origin/master):

$ git rev-list --left-right master...origin/master
<7f39ba45230f9cb052a4efd4f177f6b756194a09
<2a3fa04218d33405a2f9cbc24424263b7f1429a0

如果origin/master上的某些提交不在master上 - 例如,如果这两个中的一个在master上,而另一个在origin/master上 - 则输出会更像是:

<7f39ba45230f9cb052a4efd4f177f6b756194a09
>2a3fa04218d33405a2f9cbc24424263b7f1429a0

我认为,对称差分算子的结果最好以图形术语说明。假设我们像这样绘制部分提交图:

...--A--B--C--D     <-- branch
         \
          E--F--G   <-- origin/branch

(这是我们在处理分支branch时始终看到的那种图表:我们进行两次提交CD,然后运行{{1并且发现我们刚刚引入了三个上游提交,git fetchEF。请注意,这里没有涉及强制更新。)

使用三点表示法Gbranch...origin/branch,我们告诉Git选择上的所有提交左侧分支或< / em>右侧分支,但不在两个分支上。提交origin/branch...branch,两个分支的合并基础,在两个分支上,如提交B和所有早期提交(提交A的所有祖先)。因此,这会让我们提交BCDEF,并排除G及其所有祖先。

将此与双点表示法进行比较,例如B。在这里,我们告诉Git选择右侧的所有提交,然后排除左侧的所有提交。提交origin/branch..branchB的提交位于D,这是右侧,像branch这样的祖先以及A之前可能存在的任何内容。提交AA,当然还有BEF,以及G之前的所有内容都在左手边(A)。因此,这排除了origin/branchG以及F,这有点毫无意义,因为它们不包含在第一位,但之后也排除了E和{{1}和他们所有的祖先。这就是我们“B上仅提交 的提交。”

使用set subtraction(两个点)时,两个选择器(A)的顺序至关重要:反转它会让我们在branch上只提交 的提交,而不是origin/branch..branch上仅 的提交。当使用对称差异(三个点)时,顺序不太重要:我们在两个分支上的任何一个分支上获得所有提交。交换它们仍然会让我们提交相同的提交。该命令仅对origin/branch等装饰运算符有用,它标记对称差异的哪一侧将提交带入集合中。