如何检查远程存储库是否已更改,是否需要进行拉取?

现在我使用这个简单的脚本:

git pull --dry-run | grep -q -v 'Already up-to-date.' && changed=1

但它相当重。

有没有更好的办法?理想的解决方案是检查所有远程分支,并返回已更改分支的名称以及每个分支中新提交的数量。


当前回答

如果你有一个上游分支

git fetch <remote>
git status

如果你没有上游分支

比较这两个分支:

git fetch <remote>
git log <local_branch_name>..<remote_branch_name> --oneline

例如:

git fetch origin

# See if there are any incoming changes
git log HEAD..origin/master --oneline

(我假设原点/主人是你的远程跟踪分支)

如果上面的输出中列出了任何提交,那么您就有了传入的更改——您需要合并。如果git日志中没有列出提交,那么就没有东西可以合并。

注意,即使你在一个没有跟踪远程的特性分支上,这也可以工作,因为if显式地引用了origin/master,而不是隐式地使用Git记住的上游分支。

其他回答

如果你运行这个脚本,它将测试当前分支是否需要git拉:

#!/bin/bash

git fetch -v --dry-run 2>&1 |
    grep -qE "\[up\s+to\s+date\]\s+$(
        git branch 2>/dev/null |
           sed -n '/^\*/s/^\* //p' |
                sed -r 's:(\+|\*|\$):\\\1:g'
    )\s+" || {
        echo >&2 "Current branch need a 'git pull' before commit"
        exit 1
}

将它作为Git钩子预提交来避免非常方便

Merge branch 'foobar' of url:/path/to/git/foobar into foobar

当你承诺之前拉。

要将此代码用作钩子,只需复制/粘贴脚本即可

.git/hooks/pre-commit

and

chmod +x .git/hooks/pre-commit

在阅读了许多答案和多个帖子,并花了半天时间尝试各种排列之后,这就是我想出的。

如果你在Windows上,你可以使用Git for Windows提供的Git Bash在Windows中运行这个脚本(安装或移植)。

这个脚本需要参数

- local path e.g. /d/source/project1
- Git URL e.g. https://username@bitbucket.org/username/project1.git
- password

if a password should not be entered on the command line in plain text,
then modify the script to check if GITPASS is empty; do not
replace and let Git prompt for a password

脚本将会

- Find the current branch
- Get the SHA1 of the remote on that branch
- Get the SHA1 of the local on that branch
- Compare them.

如果脚本打印了更改,那么您可以继续获取或拉取。脚本可能效率不高,但它为我完成了工作。

更新- 2015-10-30:stderr to dev null,防止将URL和密码打印到控制台。

#!/bin/bash

# Shell script to check if a Git pull is required.

LOCALPATH=$1
GITURL=$2
GITPASS=$3

cd $LOCALPATH
BRANCH="$(git rev-parse --abbrev-ref HEAD)"

echo
echo git url = $GITURL
echo branch = $BRANCH

# Bash replace - replace @ with :password@ in the GIT URL
GITURL2="${GITURL/@/:$GITPASS@}"
FOO="$(git ls-remote $GITURL2 -h $BRANCH 2> /dev/null)"
if [ "$?" != "0" ]; then
  echo cannot get remote status
  exit 2
fi
FOO_ARRAY=($FOO)
BAR=${FOO_ARRAY[0]}
echo [$BAR]

LOCALBAR="$(git rev-parse HEAD)"
echo [$LOCALBAR]
echo

if [ "$BAR" == "$LOCALBAR" ]; then
  #read -t10 -n1 -r -p 'Press any key in the next ten seconds...' key
  echo No changes
  exit 0
else
  #read -t10 -n1 -r -p 'Press any key in the next ten seconds...' key
  #echo pressed $key
  echo There are changes between local and remote repositories.
  exit 1
fi

我认为最好的方法是:

git diff remotes/origin/HEAD

假设您已经注册了this refspec。如果您已经克隆了存储库,则应该这样做,否则(例如,如果回购是在本地从头创建的,并推到远程),则需要显式地添加refspec。

我基于@jberger的评论来解决这个问题。

if git checkout master &&
    git fetch origin master &&
    [ `git rev-list HEAD...origin/master --count` != 0 ] &&
    git merge origin/master
then
    echo 'Updated!'
else
    echo 'Not updated.'
fi

如果这是一个脚本,你可以使用:

git fetch
$(git rev-parse HEAD) == $(git rev-parse @{u})

(注意:与之前的答案相比,这个答案的好处是您不需要单独的命令来获取当前的分支名称。“HEAD”和“@{u}”(当前分支的上游)负责处理它。详见“git rev-parse——help”。)