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

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

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

但它相当重。

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


当前回答

因为尼尔的回答对我帮助很大,这里是一个没有依赖关系的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

其他回答

我使用了一个基于Stephen Haberman回答的脚本版本:

if [ -n "$1" ]; then
    gitbin="git -C $1"
else
    gitbin="git"
fi

# Fetches from all the remotes, although --all can be replaced with origin
$gitbin fetch --all
if [ $($gitbin rev-parse HEAD) != $($gitbin rev-parse @{u}) ]; then
    $gitbin rebase @{u} --preserve-merges
fi

假设此脚本名为Git -fetch-and-rebase,可以使用本地Git存储库的可选参数目录名来调用它,以执行操作。如果调用脚本时不带参数,则假定当前目录是Git存储库的一部分。

例子:

# Operates on /abc/def/my-git-repo-dir
git-fetch-and-rebase /abc/def/my-git-repo-dir

# Operates on the Git repository which the current working directory is part of
git-fetch-and-rebase

这里也有。

所有这些复杂的建议,而解决方案却如此简单:

#!/bin/bash

BRANCH="<your branch name>"
LAST_UPDATE=`git show --no-notes --format=format:"%H" $BRANCH | head -n 1`
LAST_COMMIT=`git show --no-notes --format=format:"%H" origin/$BRANCH | head -n 1`

git remote update
if [ $LAST_COMMIT != $LAST_UPDATE ]; then
        echo "Updating your branch $BRANCH"
        git pull --no-edit
else
        echo "No updates available"
fi

对于那些在这个问题上寻找答案的windows用户,我已经将部分答案修改为powershell脚本。根据需要进行调整,保存到.ps1文件,并根据需要或计划运行。

cd C:\<path to repo>
git remote update                           #update remote
$msg = git remote show origin               #capture status
$update = $msg -like '*local out of date*'
if($update.length -gt 0){                   #if local needs update
    Write-Host ('needs update')
    git pull
    git reset --hard origin/master
    Write-Host ('local updated')
} else {
    Write-Host ('no update needed')
}

运行git fetch (remote)来更新你的远程引用,它会告诉你什么是新的。然后,当您签出本地分支时,它将显示它是否落后于上游。

git ls-remote origin -h refs/heads/master

由brol给出的是检查遥控器中是否发生了变化的最简单的方法。

从局部头部开始:

$ git log -1 --oneline @
9e1ff307c779 (HEAD -> master, tag: v5.15-rc4, origin/master, origin/HEAD) Linux 5.15-rc4

我看到我拉的原点在那个标签处是最新的。Git状态也是这么说的。但这只是最新的本地数据,取数据后的(快进)合并。

检查远程HEAD是否去了某个地方,还有master,也许还有一些新标签:

$ git ls-remote origin HEAD master --tags 'v5.1[56]-rc[345]*'

84b3e42564accd94c2680e3ba42717c32c8b5fc4        HEAD
84b3e42564accd94c2680e3ba42717c32c8b5fc4        refs/heads/master
71a6dc2a869beafceef1ce46a9ebefd52288f1d7        refs/tags/v5.15-rc3
5816b3e6577eaa676ceb00a848f0fd65fe2adc29        refs/tags/v5.15-rc3^{}
f3cee05630e772378957a74a209aad059714cbd2        refs/tags/v5.15-rc4
9e1ff307c779ce1f0f810c7ecce3d95bbae40896        refs/tags/v5.15-rc4^{}

HEAD仍然在同一个分支上,但不再是同一个提交。本地@提交保留在v5.15-rc4标记中。这与kernel.org git的摘要表顶部的信息大致相同:

Branch: master <commit message> <author> age: 2 hours

只有ls-remote收集的信息更少-但只有我知道我是9e1ff…即v5.15-rc4。

除了命名引用(HEAD, master)或标签,还可以从任何repo中获得头部或分支的列表:

$ git ls-remote --heads git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git 

af06aff2a0007976513134dfe993d55992dd866a        refs/heads/akpm
20bcee8e95f783c11a7bea1b6a40c70a37873e0a        refs/heads/akpm-base
a25006a77348ba06c7bc96520d331cd9dd370715        refs/heads/master
4d5a088c93cea1c821d02a2217c592391d9682e2        refs/heads/pending-fixes
4de593fb965fc2bd11a0b767e0c65ff43540a6e4        refs/heads/stable

这里用URL代替“origin”。


如何检查远程存储库是否已经更改,而我需要更改 拉?

如果你这么问,就拔。

我如何检查远程存储库是否最终完成了一些事情,我想要拉?

然后取回,检查,合并。


使用单个git命令:

$ git rev-list -1  master
9e1ff307c779ce1f0f810c7ecce3d95bbae40896
$ git rev-list -1  @
9e1ff307c779ce1f0f810c7ecce3d95bbae40896

这本身说明不了什么,但假设我知道我什么也没做,那么:

$ git ls-remote origin HEAD master
60a9483534ed0d99090a2ee1d4bb0b8179195f51        HEAD
60a9483534ed0d99090a2ee1d4bb0b8179195f51        refs/heads/master

会告诉我遥控器换了。自从上次编辑以来确实是这样。kernel.org说年龄:46分钟。关于最后一次在master上提交。

git取回后:

$ git rev-list -1 master     
9e1ff307c779ce1f0f810c7ecce3d95bbae40896

$ git rev-list -1 FETCH_HEAD
60a9483534ed0d99090a2ee1d4bb0b8179195f51

$ git log --oneline ..FETCH_HEAD        
60a9483534ed (origin/master, origin/HEAD) Merge tag 'warning-fixes-20211005' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs
f6274b06e326 Merge tag 'linux-kselftest-fixes-5.15-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest
ef31499a87cf fscache: Remove an unused static variable
d9e3f82279bf fscache: Fix some kerneldoc warnings shown up by W=1
bc868036569e 9p: Fix a bunch of kerneldoc warnings shown up by W=1
dcb442b13364 afs: Fix kerneldoc warning shown up by W=1
c0b27c486970 nfs: Fix kerneldoc warning shown up by W=1
84b3e42564ac Merge tag 'media/v5.15-3' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
b60be028fc1a Merge tag 'ovl-fixes-5.15-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs
df5c18838ea8 Merge tag 'mips-fixes_5.15_1' of git://git.kernel.org/pub/scm/linux/kernel/git/mips/linux
206704a1fe0b media: atomisp: restore missing 'return' statement
740da9d7ca4e MIPS: Revert "add support for buggy MT7621S core detection"
1dc1eed46f9f ovl: fix IOCB_DIRECT if underlying fs doesn't support direct IO
2f9602870886 selftests: drivers/dma-buf: Fix implicit declaration warns
a295aef603e1 ovl: fix missing negative dentry check in ovl_rename()

现在我在本地拥有所有信息,但还没有合并。我还下载了所有的对象。git显示HASH或git diff HASH工作。

在这种情况下,合并几乎没有任何操作:快进到最后一次提交,没有额外的(真正的)合并,更不用说冲突了。这可以通过——ff-only来确保:

$ git merge --ff-only FETCH_HEAD
Updating 9e1ff307c779..60a9483534ed
Fast-forward
...
... 

那我怎么知道什么时候拉呢?只要这两个散列是/将是不同的:更新9e1ff307c779..60 a9483534ed快进。它们不可能是一样的,那就是“没什么可更新的”。

最新的reflog提交也是这样说的:

$ git log -10 --oneline -g
60a9483534ed (HEAD -> master, origin/master, origin/HEAD) HEAD@{0}: merge 60a9483534ed0d99090a2ee1d4bb0b8179195f51: Fast-forward
9e1ff307c779 (tag: v5.15-rc4) HEAD@{1}: pull: Fast-forward

在这种情况下,新标签的出现可能是最好的触发器和目标;返回到git ls-remote origin——tags PATTERN。


...别告诉我git remote show是另一个方法:

show给出关于遥控器的一些信息。 使用-n选项,git ls-remote不会首先查询远程头;取而代之的是使用缓存信息。