如何检查远程存储库是否已更改,是否需要进行拉取?
现在我使用这个简单的脚本:
git pull --dry-run | grep -q -v 'Already up-to-date.' && changed=1
但它相当重。
有没有更好的办法?理想的解决方案是检查所有远程分支,并返回已更改分支的名称以及每个分支中新提交的数量。
如何检查远程存储库是否已更改,是否需要进行拉取?
现在我使用这个简单的脚本:
git pull --dry-run | grep -q -v 'Already up-to-date.' && changed=1
但它相当重。
有没有更好的办法?理想的解决方案是检查所有远程分支,并返回已更改分支的名称以及每个分支中新提交的数量。
当前回答
我只是想把这篇文章作为一个实际的帖子,因为它很容易在评论中错过。
这个问题的正确答案来自@Jake Berger,非常感谢你,每个人都需要这个,每个人都在评论中错过了这个。 因此,对于每个纠结于此的人来说,这里是正确的答案,只需使用该命令的输出来了解是否需要进行git拉取。如果输出为0,那么显然没有什么要更新的。
@stackoverflow,给这家伙一个铃铛。 谢谢@杰克·伯格
# will give you the total number of "different" commits between the two
# Jake Berger Feb 5 '13 at 19:23
git rev-list HEAD...origin/master --count
其他回答
下面是我的Bash脚本版本,它可以检查预定义文件夹中的所有存储库:
https://gist.github.com/henryiii/5841984
它可以区分常见的情况,比如需要拉和需要推,而且它是多线程的,所以取回是一次性发生的。它有几个命令,比如pull和status。
把一个符号链接(或脚本)放在你路径下的文件夹中,然后它就像git all status(等)一样工作。它只支持origin/master,但可以编辑或与其他方法组合。
git ls-remote | cut -f1 | git cat-file --batch-check >&-
将列出所有在任何远程引用,不在你的回购。要捕捉你已经拥有的东西的远程引用更改(例如,重置到以前的提交)需要更多一点:
git pack-refs --all
mine=`mktemp`
sed '/^#/d;/^^/{G;s/.\(.*\)\n.* \(.*\)/\1 \2^{}/;};h' .git/packed-refs | sort -k2 >$mine
for r in `git remote`; do
echo Checking $r ...
git ls-remote $r | sort -k2 | diff -b - $mine | grep ^\<
done
在阅读了许多答案和多个帖子,并花了半天时间尝试各种排列之后,这就是我想出的。
如果你在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
因为尼尔的回答对我帮助很大,这里是一个没有依赖关系的Python翻译:
import os
import logging
import subprocess
def check_for_updates(directory:str) -> None:
"""Check git repo state in respect to remote"""
git_cmd = lambda cmd: subprocess.run(
["git"] + cmd,
cwd=directory,
stdout=subprocess.PIPE,
check=True,
universal_newlines=True).stdout.rstrip("\n")
origin = git_cmd(["config", "--get", "remote.origin.url"])
logging.debug("Git repo origin: %r", origin)
for line in git_cmd(["fetch"]):
logging.debug(line)
local_sha = git_cmd(["rev-parse", "@"])
remote_sha = git_cmd(["rev-parse", "@{u}"])
base_sha = git_cmd(["merge-base", "@", "@{u}"])
if local_sha == remote_sha:
logging.info("Repo is up to date")
elif local_sha == base_sha:
logging.info("You need to pull")
elif remote_sha == base_sha:
logging.info("You need to push")
else:
logging.info("Diverged")
check_for_updates(os.path.dirname(__file__))
hth
如果这是一个脚本,你可以使用:
git fetch
$(git rev-parse HEAD) == $(git rev-parse @{u})
(注意:与之前的答案相比,这个答案的好处是您不需要单独的命令来获取当前的分支名称。“HEAD”和“@{u}”(当前分支的上游)负责处理它。详见“git rev-parse——help”。)