如何知道git仓库是否有未与服务器(origin)同步的更改?

14

我在Git中设置了大量项目,这些项目之前是在CVS中管理的。Tortoise CVS以及Eclipse都可以通过图标覆盖来轻松查看是否对存储库进行了更改,但这些更改尚未发送到中央服务器。

那么,在Git中有没有方便的方法实现这一点呢?我不需要图标覆盖——我只需要知道当将我的分支与源分支进行比较时,是否存在未完成的更改。我不介意使用某种脚本来查询所有Git仓库。

4个回答

8

类似 git log origin/master..master 这样的命令可以让你查看已经提交但未推送的提交记录。如果你先执行 git fetch origin,然后再执行 git log master..origin/master,你就可以查看远程主分支上的提交记录。你也可以使用 git log origin/master...master 命令来查看本地和远程的新提交。

如果需要,在脚本中可以将 git log 替换为 git rev-list,以便轻松确定哪些提交尚未推送。


以下命令对我无效:$ 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

7
以下示例仅涉及单个存储库。在周围的脚本中使用循环来在多个存储库上运行它们。
在使用以下命令之前,您可能希望运行(例如)git fetch origin来更新本地远程跟踪分支(以便您检查最新的上游分支提示)。
如果您只关心当前检出的分支:
git status -sb

如果第一行报告“ahead”,那么当前分支有一些提交不属于它的上游分支。这个命令的输出不适合直接被程序使用(它是一个“瓷器”命令)。对于编程式的使用,可以使用“plumbing”命令来列出“ahead”提交:(参见链接)
git rev-list HEAD@{upstream}..HEAD

您可以将其传输到wc -l以获取计数。如果您只对“ahead”状态感兴趣(而不是确切的计数),那么test -n "$(git rev-list -n 1 HEAD@{upstream}..HEAD)"可能更快。
如果您想检查存储库的所有分支:
git branch -v

再次提醒,针对那些包含不属于上游分支的提交记录的分支,您将看到“ahead”这个词。这也是一个“瓷器式”命令,因此,如果您想在程序中可靠地检测状态,则需要使用一些“管道式”命令:

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语句(或用其他命令替换它们)。


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

1
如果您有一个名为origin的远程仓库,请尝试运行以下命令:
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)

这表明我的本地分支htmlmaster已经过时。如果我的远程仓库有未在本地仓库中的提交,它将显示在为git pull配置的分支部分。

用任何远程仓库的名称替换origin

如果您不知道您的源的名称或其URL,请尝试以下操作:

git remote -v

这将为您提供远程存储库及其URL的列表。

编辑以添加

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


我目前很喜欢这个,但我需要一次将其应用于大量项目并聚合输出。具体来说,如果我的推送分支超前于原始分支,而我的拉取分支落后,则考虑使用子模块来方便在多个子存储库上运行脚本。 - Andy

0

昨天我尝试自己编写解决方案。这是我为单个存储库想出的:

#!/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”命令在提供的参数下正在执行什么操作——但它似乎输出了我想要的信息。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接