如何检查远程存储库是否已更改,我需要拉?
现在我使用这个简单的脚本:
git pull --dry-run | grep -q -v 'Already up-to-date.' && changed=1
Run Code Online (Sandbox Code Playgroud)
但它相当沉重.
有没有更好的办法?理想的解决方案是检查所有远程分支,并返回已更改分支的名称和每个分支的新提交数.
Nei*_*hew 818
首次使用git remote update
,让您的遥控器更新.然后你可以做以下几件事之一,例如:
git status -uno
会告诉你你正在跟踪的分支是在前面,后面还是分歧.如果没有说什么,本地和远程都是一样的.
git show-branch *master
将显示所有名称以"master"结尾的分支(例如master和origin/master)中的提交.
如果使用-v
with git remote update
(git remote -v update
),您可以看到哪些分支已更新,因此您不需要任何其他命令.
但是,看起来您希望在脚本或程序中执行此操作,并最终得到true/false值.如果是这样,有一些方法可以检查当前HEAD提交与您正在跟踪的分支的负责人之间的关系,尽管由于有四种可能的结果,您无法将其减少为是/否答案.但是,如果你准备做一个,pull --rebase
那么你可以将"本地落后"和"本地分歧"视为"需要拉动",另外两个则称为"不需要拉动".
您可以获取任何ref使用的提交ID git rev-parse <ref>
,因此您可以为master和origin/master执行此操作并进行比较.如果它们相等,则分支是相同的.如果他们不平等,你想知道哪一个先于另一个.使用git merge-base master origin/master
将告诉你两个分支的共同祖先,如果它们没有分歧,这将是一个或另一个相同.如果你得到三个不同的ID,那么分支就会分歧.
要正确执行此操作(例如,在脚本中),您需要能够引用当前分支以及它正在跟踪的远程分支.bash提示设置函数/etc/bash_completion.d
包含一些用于获取分支名称的有用代码.但是,您可能实际上并不需要获取名称.Git有一些简洁的缩写用于引用分支和提交(如文档中所述git rev-parse --help
).特别是,您可以使用@
当前分支(假设您不处于分离头状态)和@{u}
其上游分支(例如origin/master
).因此,git merge-base @ @{u}
将返回当前分支及其上游分歧的提交(哈希)git rev-parse @
,git rev-parse @{u}
并将为您提供两个提示的哈希值.这可以在以下脚本中进行总结:
#!/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
Run Code Online (Sandbox Code Playgroud)
注意:旧版本的git本身不允许@
,因此您可能需要使用它@{0}
.
该行UPSTREAM=${1:-'@{u}'}
允许您可选地显式传递上游分支,以防您要检查与为当前分支配置的远程分支不同的远程分支.这通常是remotename/branchname的形式.如果未给出参数,则值默认为@{u}
.
该脚本假设您已完成git fetch
或git remote update
首先执行,以使跟踪分支更新.我没有将它构建到脚本中,因为它能够更灵活地进行提取和比较作为单独的操作,例如,如果你想比较而不提取,因为你最近已经提取了.
Pla*_*mer 129
git fetch <remote>
git status
Run Code Online (Sandbox Code Playgroud)
比较两个分支:
git fetch <remote>
git log <local_branch_name>..<remote_branch_name> --oneline
Run Code Online (Sandbox Code Playgroud)
例如:
git fetch origin
# See if there are any incoming changes
git log HEAD..origin/master --oneline
Run Code Online (Sandbox Code Playgroud)
(我假设origin/master
你是远程跟踪分支)
如果上面的输出中列出了任何提交,那么您有传入的更改 - 您需要合并.如果没有列出提交,git log
则没有任何内容可以合并.
请注意,即使您位于功能分支上(即没有跟踪远程),这也会起作用,因为如果显式引用origin/master
而不是隐式使用Git记住的上游分支.
Ste*_*man 61
如果是脚本,您可以使用:
git fetch
$(git rev-parse HEAD) == $(git rev-parse @{u})
Run Code Online (Sandbox Code Playgroud)
(注意:这与以前的答案相比,你不需要单独的命令来获取当前的分支名称."HEAD"和"@ {u}"(当前分支的上游)负责处理它. "git rev-parse --help"了解更多详情.)
bro*_*ool 36
命令
git ls-remote origin -h refs/heads/master
Run Code Online (Sandbox Code Playgroud)
将列出遥控器上的当前头部 - 您可以将其与之前的值进行比较,或者查看您的本地仓库中是否有SHA.
wjo*_*dan 33
这是一个Bash单行程序,它将当前分支的HEAD提交哈希与其远程上游分支进行比较,不需要繁重git fetch
或git pull --dry-run
需要操作:
[ $(git rev-parse HEAD) = $(git ls-remote $(git rev-parse --abbrev-ref @{u} | \
sed 's/\// /g') | cut -f1) ] && echo up to date || echo not up to date
Run Code Online (Sandbox Code Playgroud)
这是一个有点密集的线被分解的方式:
$(x)
Bash 命令替换语法对命令进行分组和嵌套.git rev-parse --abbrev-ref @{u}
返回缩写的上游ref(例如origin/master
),然后通过管道sed
命令将其转换为空格分隔的字段,例如origin master
.git ls-remote
其中,返回远程分支的头部提交.此命令将与远程存储库通信.piped cut
命令仅提取第一个字段(提交哈希),删除以制表符分隔的引用字符串.git rev-parse HEAD
返回本地提交哈希.[ a = b ] && x || y
完成了单行:这是测试构造中的Bash 字符串比较 ,后跟and-list和or-list构造.=
[ test ]
&& true || false
Bru*_*elé 20
我建议你去看看脚本https://github.com/badele/gitcheck.我已经编写了这个脚本,以便一次性检查所有Git存储库,并显示谁没有提交,谁没有推/拉.
这是一个示例结果:
ma1*_*w28 10
我的解决方案基于@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
Run Code Online (Sandbox Code Playgroud)
我认为最好的方法是:
git diff remotes/origin/HEAD
Run Code Online (Sandbox Code Playgroud)
假设您已注册此refspec.您应该克隆存储库,否则(即,如果repo是在本地创建并推送到远程),则需要显式添加refspec.
已经有许多功能丰富且巧妙的答案.为了提供一些对比,我可以用一个非常简单的线来做.
# 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
Run Code Online (Sandbox Code Playgroud)
以下脚本完美无缺.
changed=0
git remote update && git status -uno | grep -q 'Your branch is behind' && changed=1
if [ $changed = 1 ]; then
git pull
echo "Updated successfully";
else
echo "Up-to-date"
fi
Run Code Online (Sandbox Code Playgroud)
我会按照布鲁尔建议的方式行事.以下单行脚本获取上次提交的版本的SHA1,并将其与远程源的SHA1进行比较,并仅在它们不同时才进行更改.它的重量甚至更轻,基于git pull
或git fetch
.
[ `git log --pretty=%H ...refs/heads/master^` != `git ls-remote origin
-h refs/heads/master |cut -f1` ] && git pull
Run Code Online (Sandbox Code Playgroud)
如果您运行此脚本,它将测试当前分支是否需要git pull
:
#!/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
}
Run Code Online (Sandbox Code Playgroud)
将它作为Git钩子预先提交以避免它是非常方便的
Merge branch 'foobar' of url:/path/to/git/foobar into foobar
Run Code Online (Sandbox Code Playgroud)
当你commit
之前pulling
.
要将此代码用作挂钩,只需复制/粘贴脚本即可
.git/hooks/pre-commit
Run Code Online (Sandbox Code Playgroud)
和
chmod +x .git/hooks/pre-commit
Run Code Online (Sandbox Code Playgroud)
所有这些复杂的建议,而解决方案是如此简短和简单:
#!/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
Run Code Online (Sandbox Code Playgroud)
我只想将其发布为实际发布,因为很容易在评论中错过它。
@Jake Berger给出了这个问题的正确和最佳答案,非常感谢,伙计,每个人都需要这个,每个人都在评论中错过了。因此,对于每个在此方面苦苦挣扎的人来说,这都是正确的答案,只需使用此命令的输出即可知道是否需要执行git pull。如果输出为0,则显然没有任何更新。
@stackoverflow,给这个家伙一个钟声。谢谢@杰克·伯格
git rev-list HEAD...origin/master --count will give you the total number of "different" commits between the two. – Jake Berger Feb 5 '13 at 19:23
Run Code Online (Sandbox Code Playgroud)