问题 如何知道git存储库是否有未与服务器(源)同步的更改?


我在Git中设置了大量项目,这些项目以前是在CVS中管理的。如果我对尚未发送到中央服务器的存储库进行了更改,那么Tortoise CVS以及Eclipse都很容易看到(通过图标叠加)。

有没有一种方便的方法来实现这一点与Git?我真的不需要图标叠加 - 我只需要知道在将我的分支与原始分支进行比较时是否有突出的变化。我不介意使用某种脚本来查询所有的Git repos。


8590
2018-05-25 15:37


起源



答案:


就像是 git log origin/master..master 应该给你你做过的提交,而不是推。如果您获取原点然后执行 git log master..origin/master 你可以在远程master中看到提交。你也可以这样做 git log origin/master...master 查看本地和远程的新提交。

你可以替换 git log 同 git rev-list 并且如果需要,可以轻松地确定脚本中是否以及未推送的内容。


8
2018-05-25 15:42



这些对我不起作用:$ git log origin/master..master fatal: ambiguous argument 'origin/master..master': unknown revision or path not in the working tree. Use '--' to separate paths from revisions - Catfish
你有两个点而不是三个点,运行“master ... master”而不是“master..master” - Ricky Levi


答案:


就像是 git log origin/master..master 应该给你你做过的提交,而不是推。如果您获取原点然后执行 git log master..origin/master 你可以在远程master中看到提交。你也可以这样做 git log origin/master...master 查看本地和远程的新提交。

你可以替换 git log 同 git rev-list 并且如果需要,可以轻松地确定脚本中是否以及未推送的内容。


8
2018-05-25 15:42



这些对我不起作用:$ git log origin/master..master fatal: ambiguous argument 'origin/master..master': unknown revision or path not in the working tree. Use '--' to separate paths from revisions - Catfish
你有两个点而不是三个点,运行“master ... master”而不是“master..master” - Ricky Levi


以下示例仅处理单个存储库。在周围的脚本中使用循环在多个存储库上运行它们。

您可能想要运行(例如) git fetch origin 在使用以下命令之前更新本地远程跟踪分支(以便您检查上游分支的最新提示)。

如果您只关心当前签出的分支:

git status -sb

如果第一行报告“提前”,则当前分支具有不属于其上游分支的提交。该命令的输出不适合程序直接使用(它是“瓷器”命令)。对于程序化消费使用a “管道”命令 列出“提前”提交:

git rev-list HEAD@{upstream}..HEAD

你可以把它管道 wc -l 得到一个数。如果您只对“提前”状态(不是确切的计数)感兴趣,那么 test -n "$(git rev-list -n 1 HEAD@{upstream}..HEAD)" 可能会更快。

如果要检查存储库的所有分支:

git branch -v

同样,对于具有不属于其上游分支的提交的分支,您将看到“超前”。这也是一个“瓷器”命令,所以如果你想要可靠地检测程序中的状态,那么你会想要使用一些“管道”命令:

git for-each-ref --shell --format='
    b=%(refname:short)
    u=${b}'@{upstream}'
    if git rev-parse --verify --quiet "$u" >/dev/null 2>&1; then
        test -n "$(git rev-list -n 1 "$u..$b")" &&
        echo "$b: has unpushed commits"
    else
        echo "$b: no upstream configuration" >&2
    fi
' refs/heads | sh

调整 echo 声明(或用其他命令替换它们)以满足您的目的。


5
2018-05-26 05:12



尼斯。如果要检查本地和上游分支的更改,可以使用git的三点语法。 git rev-list HEAD@{upstream}...HEAD1 - Christian Long


如果你有一个命名的遥控器,比如原点,那么试试这个:

git remote show origin

这将给你一个很好的总结。

例如,这就是我得到的

git % git remote show origin
* remote origin
  Fetch URL: git://git.kernel.org/pub/scm/git/git.git
  Push  URL: git://git.kernel.org/pub/scm/git/git.git
  HEAD branch: master
  Remote branches:
    html   tracked
    maint  tracked
    man    tracked
    master tracked
    next   tracked
    pu     tracked
    todo   tracked
  Local branches configured for 'git pull':
    html   merges with remote html
    master merges with remote master
  Local refs configured for 'git push':
    html   pushes to html   (local out of date)
    master pushes to master (local out of date)

这表明我当地的分支机构 html 和 master 已经过时了。如果我的遥控器有不在我本地仓库中的提交 - 它将显示在为git pull配置的分支部分中。

更换 origin 具有任何远程存储库的名称。

如果您不知道您的姓名是什么,或者他们的网址是这样的:

git remote -v

这将为您提供遥控器及其URL的列表。

编辑添加

如果您有许多子模块,您可以使用 git submodule foreach正如我所描述的那样 这里。您可以重定向输出并解析它以获得所需内容。


1
2018-05-25 15:41



到目前为止我喜欢这个,但我需要立即将它应用于大量项目并汇总输出。特别是如果我的推动分支在原点之前并且如果我的拉分支落后。我正在考虑使用子模块,以便于在多个子存储库上运行脚本。 - Andy
@Andy - 我已经更新了我的答案 - Abizern


昨天我试图推出自己的解决方案。这是我想出的(针对单个存储库):

#!/bin/sh

for ref in $(git for-each-ref --format='%(refname)' refs/remotes/); do
    ending=${ref#refs/remotes/}
    remote=${ending%/*}
    branch=${ending#*/}
    if [ "${branch}" == "HEAD" ]; then continue; fi
    echo -e "\e[1;34m$branch on $remote\e[0m"
    echo "AHEAD by:"
    git log --oneline $branch ^$remote/$branch
    echo "BEHIND by:"
    git log --oneline $remote/$branch ^$branch
done

这是基于信息我已经提取了几个来源,包括这里的答案。考虑到我提供的参数,我对'git log'命令正在做什么仍然有点阴暗 - 但它似乎吐出了我想要的那种信息。


0
2018-05-26 14:12