【问题标题】:Select remote on Git status在 Git 状态上选择远程
【发布时间】:2018-03-31 09:39:26
【问题描述】:

我可以使用git status 告诉我我是在遥控器前面还是后面:

git status
On branch master
Your branch is ahead of 'bean/master' by 1 commit.
  (use "git push" to publish your local commits)
nothing to commit, working tree clean

哪个适合解析:

needs_push = "Your branch is ahead" in std.out
needs_pull = "Your branch is behind" in std.out

但是,当使用多个遥控器时,事情会失败,因为git status 只显示一个遥控器的结果(上例中的bean)并且不带任何参数来选择遥控器。

我有什么方法可以指定要显示详细信息的遥控器吗? 即给定两个遥控器,我的本地存储库/分支是否需要推送和/或拉取,如果需要,哪个? “需要拉动”是指遥控器包含我没有得到的提交,而“需要推送”是指我有遥控器没有的提交。 (即假设一个没有什么深奥的线性工作流程。)

如果我可以使用 URL 而不是名称会更好,但据我所知,git 只能在调用 git remote update 后描述遥控器。

【问题讨论】:

  • 我不完全理解您的要求,因为git status 显示了给定分支的状态。在我看来,一个分支只有一个遥控器是事后的想法。你能澄清一下你想在这里做什么吗?
  • 您有git log <branch>...<someremote/branch1>git diff <branch>..<someremote/branch1> 以您提到的方式向您显示比git status 更多的信息。
  • 我想知道我是否应该拉动和/或推向/从我的两个遥控器中的每一个(不实际拉动或推动)
  • “应该”拉或推是您创建的概念。 git-status 仅显示您的分支与其跟踪分支之间的提交差异。如果这意味着你应该拉或推,这取决于你。如果您需要查看您的分支和某个未跟踪的分支之间的提交,您需要将其设置为跟踪分支或使用git-loggit-diff 或其他命令。
  • @cz 很高兴我能帮上忙 :) 不过,我认为您应该检查有关 refspecs 的文档并尝试将它们与 git-log 一起使用,这可能会更完整。

标签: git


【解决方案1】:

如果我可以使用 URL 而不是名称会更好,但据我所知,git 只能在调用 git remote update 后描述遥控器。

没错,虽然有点不准确。这里“幕后”发生的事情是,一旦你完成了git fetchgit remote update,只需将git fetch 或多或少运行到各种遥控器,你可以从git fetch 本身执行此操作,所以使用任何命令你更喜欢,他们在这里基本上做同样的事情——你的 Git 现在在你的存储库中拥有他们的 Git 拥有的每一个提交; 您的Git 已更新您的远程跟踪分支名称,例如origin/masterbean/master 以及您拥有的任何其他遥控器。

因此,既然您拥有他们所拥有的以及更多(如果还有更多的话),您现在可以确定您拥有的任何给定分支名称是否指向:

  • 与某个远程跟踪分支名称相同的提交;
  • 较早在同一提交链上提交;
  • 稍后在同一提交链上提交;或
  • 一个完全不相关的提交。

(最后一种情况不太可能,但为了完整起见,应该提及。)

提交链:提交图

这些提交链是由提交图或 DAG 形成的:

A <-B <-C   <-- master

代表一个非常简单的存储库,只有三个提交。我们说 name master“指向”提交 C,因为 master 包含大而丑陋的哈希 ID,它是提交 C 的“真实名称”。同时commit C包含commit B的hash ID,所以C指向B;同样,B 指向ABC 的父级,AB 的父级。

由于A 是第一次提交,它没有父提交ID;所以它没有。这使它成为 root 提交,并且它没有指向任何地方,这意味着 git log 可以停止打印内容。我们或git log 将从名称master 开始并查看提交C,然后按照C 的箭头返回B 并查看B。然后它会沿着向后的箭头到A并查看A,现在它已经没有东西可以跟随了。

当您 git fetch 一个新的提交 DC 作为其父级时,我们会得到稍微复杂的图片:

A--B--C   <-- master
       \
        D   <-- bean/master

从这张图中很容易看出bean/mastermaster 的“提前一次提交”。但是在内部,所有的Git箭头都是向后工作的,所以实际上Git必须从bean/master开始并工作back,当它找到提交Cmaster时,我们就知道了master 落后于 bean/master

作为AnimiVulpis answered(已投票),您可以使用--countgit rev-list 为您计数 次提交。通常它只列出提交哈希。就像git log:它从您告诉它开始的提交开始,并沿着内部“箭头”从一个提交向后退到另一个。如果你给它一个 stopping 点,它会在它到达作为停止点的提交时停止,或者——这部分有点棘手——可从停止点到达 .

让我们画一张稍微复杂一点的图,你在master 上做了一个新的提交——我们称之为E——并从bean 中引入D 来生成bean/master 点给它:

        E   <-- master
       /
A--B--C
       \
        D   <-- bean/master

现在masterbean/master 之前的一个提交,bean/mastermaster 之前的一个提交,同时。这是因为如果我们从master 开始并向后工作,我们会发现一个从bean/master 开始并向后工作无法达到的提交。如果我们反过来开始,情况也是如此。

因此,我们需要 两个 git rev-list 命令。我们将使用master ^bean/master aka bean/master..master 运行一个:从master 开始,在达到提交C 时停止,因为它可以从bean/master 访问。这将在master 上提交E,然后停止。另一个,我们将使用bean/master ^master aka master..bean/master:以bean/master 开始,并在达到提交C 时停止,因为它可以从master 访问。

这个可达性 概念是使 Git 工作的关键图论位之一。可视化它的一个好方法是想象为每个提交临时着色,就像使用荧光笔一样:我们将一些提交着色为红色作为“停止”,将其他提交着色为绿色作为“开始”,如果我们同时这样做,红色往往会覆盖绿色颜色“同时”。 X ^Y 表示法使用从X 开始的绿色和从Y 开始的红色Y..X 符号只是同一事物的简写。

对称差异使这更容易

事实证明,Git 有一个特殊的符号,X...Y(三个点而不是两个),表示 对称差异:如果从 只有一个 的起点,但如果从两者都可以到达,则为红色。在此图中,bean/master...master 将选择提交 E——可从 master 访问,但不是 bean/master——提交 D,但会拒绝提交 C 和更早的时间。 p>

这在这里似乎并不那么有用,直到您发现git rev-list 也有一个--left-right 选项。当将此选项与对称差异三点语法一起使用时,Git 会注意到哪些提交来自“左名称”(bean/master),哪些提交来自“右名称”(master)。通常,当git rev-list 吐出提交哈希ID 时,它使用&lt;&gt; 来标记这些。但是如果你添加--count,Git 只会像往常一样计算它们,然后打印 两个 数字:

git rev-list --count bean/master...master

左边的数字是从bean/master 到达但不能从master 到达的提交数,右边的数字是从master 到达但不能从bean/master 到达的提交数。

而且——啊哈!——这些正是git status 为“后面”和“前面”打印的计数。 (如果您愿意,可以交换名称以按其他顺序获取它们。)

警告:不相关的分支

如果您使用不相关的存储库或git checkout --orphan,您可以创建一个包含不相交子图的存储库:

A--B--C   <-- master

D--E   <-- unrelated/master

在这种情况下,对称差异表示法将列出或计算两个分支上的所有提交,因为它所做的只是列出或计算可从任一名称访问但不能从两个名称访问的提交。由于父链永远不会聚集在一起,因此 no 可以从两者中访问。

如果你真的需要,你可以检测到这种情况——当它发生时,两个名称之间没有合并基础——但通常一开始就不应该发生。请注意,具有多个根并不能保证,因为我们可以故意合并不相关的历史:

A--B
    \
     E--F   <-- branch
    /
C--D

我们甚至可以在合并后有一个分叉:

A--B      G   <-- br1
    \    /
     E--F
    /    \
C--D      H--I   <-- br2

但是这些分支确实有一个合并基础提交(它是提交F,从图中很明显)。

【讨论】:

    【解决方案2】:

    方法 A

    也许更容易(取决于您想要实现的目标):

    • $ git rev-list--count &lt;branch-name&gt;..&lt;remote&gt;/&lt;remote-branch-name&gt;

    将输出第一个分支在远程分支后面的提交次数

    • $ git rev-list--count &lt;remote&gt;/&lt;remote-branch-name&gt;..&lt;branch-name&gt;

    将输出第一个分支在远程分支之前的提交次数

    使用此命令,您可以列出您可能想知道的各种事情。但是你需要先了解gitrevisions

    $ git rev-list --count <some git revision specification>
    

    方法 B

    根据您打算如何处理这些信息,以下内容可能会派上用场:

    输出将如下所示:

    # branch.oid <hash>
    # branch.head example-branch
    # branch.upstream origin/example-branch-developer-1
    # branch.ab +0 -1
    

    最后一行是你最感兴趣的,格式如下:

    # branch.ab +&lt;ahead&gt; -&lt;behind&gt;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-15
      • 2017-03-10
      • 1970-01-01
      • 1970-01-01
      • 2016-04-27
      • 1970-01-01
      • 2010-10-10
      • 2016-11-24
      相关资源
      最近更新 更多