如何检查远程存储库是否已更改,是否需要进行拉取?
现在我使用这个简单的脚本:
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
但它相当重。
有没有更好的办法?理想的解决方案是检查所有远程分支,并返回已更改分支的名称以及每个分支中新提交的数量。
当前回答
自动化git拉取所需的分支: 例如:./pull.sh "origin/main"
pull.sh
#!/bin/bash
UPSTREAM=${1:-'@{u}'}
DIFFCOMM=$(git fetch origin --quiet; git rev-list HEAD..."$UPSTREAM" --count)
if [ "$DIFFCOMM" -gt 0 ]; then
echo "Pulling $UPSTREAM";
git pull;
else
echo "Up-to-date";
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
我只是想把这篇文章作为一个实际的帖子,因为它很容易在评论中错过。
这个问题的正确答案来自@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
使用简单的regexp:
str=$(git status)
if [[ $str =~ .*Your\ branch\ is\ behind.*by.*commits,\ and\ can\ be\ fast-forwarded ]]; then
echo `date "+%Y-%m-%d %H:%M:%S"` "Needs pull"
else
echo "Code is up to date"
fi
首先使用git远程更新,使您的远程参考更新到最新。然后你可以做以下几件事中的一件,比如:
Git status -uno将告诉你你正在跟踪的分支是在前面、后面还是已经偏离。如果没有显示,则本地和远程是相同的。 Git show-branch *master会显示所有以master结尾的分支中的提交(例如master和origin/master)。
如果你在git远程更新(git remote -v update)中使用-v,你可以看到哪些分支被更新了,所以你真的不需要任何进一步的命令。
However, it looks like you want to do this in a script or program and end up with a true/false value. If so, there are ways to check the relationship between your current HEAD commit and the head of the branch you're tracking, although since there are four possible outcomes you can't reduce it to a yes/no answer. However, if you're prepared to do a pull --rebase then you can treat "local is behind" and "local has diverged" as "need to pull", and the other two ("local is ahead" and "same") as "don't need to pull".
你可以使用git rev-parse <ref>获得任何ref的提交id,所以你可以对master和origin/master这样做并比较它们。如果它们相等,那么分支是相同的。如果它们不相等,你想知道哪个在前面。使用git merge-base master origin/master会告诉你两个分支的共同祖先,如果它们没有分叉,这将是一个或另一个相同的。如果您得到三个不同的id,则分支已经分离。
To do this properly, eg in a script, you need to be able to refer to the current branch, and the remote branch it's tracking. The bash prompt-setting function in /etc/bash_completion.d has some useful code for getting branch names. However, you probably don't actually need to get the names. Git has some neat shorthands for referring to branches and commits (as documented in git rev-parse --help). In particular, you can use @ for the current branch (assuming you're not in a detached-head state) and @{u} for its upstream branch (eg origin/master). So git merge-base @ @{u} will return the (hash of the) commit at which the current branch and its upstream diverge and git rev-parse @ and git rev-parse @{u} will give you the hashes of the two tips. This can be summarized in the following script:
#!/bin/sh
UPSTREAM=${1:-'@{u}'}
LOCAL=$(git rev-parse @)
REMOTE=$(git rev-parse "$UPSTREAM")
BASE=$(git merge-base @ "$UPSTREAM")
if [ $LOCAL = $REMOTE ]; then
echo "Up-to-date"
elif [ $LOCAL = $BASE ]; then
echo "Need to pull"
elif [ $REMOTE = $BASE ]; then
echo "Need to push"
else
echo "Diverged"
fi
注意:旧版本的git不允许@单独使用,所以你可能不得不使用@{0}代替。
UPSTREAM=${1:-'@{u}'}允许你显式地传递一个上游分支,以防你想检查一个不同于当前分支配置的远程分支。这通常是remotename/branchname的形式。如果不指定参数,默认值为@{u}。
该脚本假设您已经首先进行了git获取或git远程更新,以使跟踪分支更新到最新。我没有把这个构建到脚本中,因为它更灵活,能够将抓取和比较作为单独的操作,例如,如果你想比较而不抓取,因为你最近已经获取了。
已有许多很有特色、很丰富、很巧妙的答案。为了提供一些对比,我可以使用非常简单的线条。
# Check return value to see if there are incoming updates.
if ! git diff --quiet remotes/origin/HEAD; then
# pull or whatever you want to do
fi