如何检查远程仓库是否有变化,我需要去拉?
现在我用这个简单的脚本:
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 remote update
,带给你的远程裁判是最新的。 然后,你可以做的几件事情,如一个:
git status -uno
会告诉你,你所跟踪的分支是否领先,落后或已发散。 如果什么都不说,本地和远程是相同的。
git show-branch *master
会显示在所有后缀名为“主”(如主 产地和/主 )分支的提交。
如果使用-v
与git remote update
( git remote -v update
),你可以看到哪些分支得到了更新,所以你并不真正需要的任何进一步的命令。
然而,它看起来像你想这样做的脚本或程序,并用真/假值结束。 如果是这样,有很多方法可以检查您当前HEAD提交和您所跟踪的分支的头之间的关系,虽然因为有四种可能的结果,你不能把它降低到是/否的答案。 但是,如果你准备做一个pull --rebase
那么你可以把“本地的背后”和“地方已发散”为“需要拉”,另两个为“不需要拉”。
你可以使用任何裁判的提交ID git rev-parse <ref>
这样你就可以对主 产地和/主做到这一点并加以比较。 如果他们是平等的,树枝是相同的。 如果他们是不平等的,你要知道哪个是领先于其他的。 使用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
注:旧版本的Git不允许@
自身的,所以你可能需要使用@{0}
来代替。
线UPSTREAM=${1:-'@{u}'}
允许你任选明确地传送的上游分支,如果要检查针对除所述一个构造成用于当前分支不同的远程分支。 这通常是形式的远程名称/ BRANCHNAME的。 如果没有指定参数,则默认值为@{u}
。
脚本假设你已经做了一个git fetch
或git remote update
首先带来的跟踪分支是最新的。 因为,如果你想不取,因为你已经最近取出的比较更灵活,能够做的抓取和比较作为单独的操作,例如我没有建立到脚本这一点。
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
(我假设origin/master
是你的远程跟踪分支)
如果任何承诺都在上面的输出中,那么你有来电的变化 - 你需要合并。 如果没有提交由上市git log
那么就没有什么合并。
请注意,这会工作,即使你是一个特性分支-即不具有远程跟踪,因为如果明确是指origin/master
,而不是隐式使用的Git想起上游分支的。
如果这是一个脚本,您可以使用:
git fetch
$(git rev-parse HEAD) == $(git rev-parse @{u})
(注意:这与以前的答案的好处是,你并不需要一个单独的命令来获得当前分支名“HEAD”和“@ {蓝}”(当前分支的上游)照顾它见“混帐REV-解析--help”的更多细节。)
命令
git ls-remote origin -h refs/heads/master
将列出遥控器上的现任掌门人 - 你可以把它比作一个以前的值或者看看你是否有SHA在您的本地回购。
这里的一个击单行,用于比较当前分支的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
下面是这个有点密集的线路是怎样分解:
$(x)
击命令取代语法。 git rev-parse --abbrev-ref @{u}
返回一个缩写上游REF(例如origin/master
),其随后由管道转换成空间分隔的字段sed
命令,例如origin master
。 git ls-remote
它返回头提交所述远程分支。 此命令将与远程存储库进行通信。 的管道cut
命令提取只是第一场(提交散列),除去所述制表符分隔的引用字符串。 git rev-parse HEAD
返回本地提交哈希值。 [ a = b ] && x || y
[ a = b ] && x || y
完成单行:这是一个bash 字符串比较 =
测试构建体中[ test ]
,接着与列表和或列表构建&& true || false
&& true || false
。 我建议你去看看剧本https://github.com/badele/gitcheck 。 我已经编写此脚本检查一次走你所有的Git仓库,它显示谁没有犯,谁没有推/拉。
这里的样本结果:
我基于@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
有很多非常丰富的特性和巧妙的回答了。 为了提供一些对比,我能凑合着用一个非常简单的线条。
# 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
我想这样做,这将是最好的方法:
git diff remotes/origin/HEAD
假设你有这样的Refspec注册。 你应该如果你克隆的资源库,否则(即,如果回购创建从头本地,并推到远程),则需要明确添加的Refspec。
我会做的brool建议的方式。 下面的一行脚本需要你的最后COMMITED版本的SHA1,并将其与远程起源的一个,拉的变化,只有当他们是不同的。 而且它是一个基于解决方案的更轻质git pull
或git fetch
。
[ `git log --pretty=%H ...refs/heads/master^` != `git ls-remote origin
-h refs/heads/master |cut -f1` ] && git pull
下面的脚本完美的作品。
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
如果您运行此脚本,它将测试,如果当前分支需要一个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
}
这是非常方便的把它作为一个Git挂钩预提交,以避免
Merge branch 'foobar' of url:/path/to/git/foobar into foobar
当你commit
前pulling
。
要使用此代码作为一个钩子,简单的复制/粘贴脚本
.git/hooks/pre-commit
和
chmod +x .git/hooks/pre-commit
我只是想张贴此作为一个实际的职位,因为它很容易在评论错过本作。
对于这个问题的正确和最好的答案被@Jake伯格给出,非常感谢你的家伙,每个人都需要这个,每个人都错过本中的注释。 所以大家有这个挣扎在这里是正确的答案,只是使用此命令的输出知道,如果你需要做一个git的拉动。 如果输出为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
运行git fetch (remote)
来更新您的远程裁判,它会告诉你什么是新的。 然后,当你检出你的本地分支,它会告诉你它是否是背后的上游。
这里是我的一个bash脚本,将检查预定义的文件夹中的所有存储库的版本:
https://gist.github.com/henryiii/5841984
它可以与常见的情况区分,像拉推所需的必要,它是多线程的,所以取一切发生一次。 它有几个命令,如拉和状态。
将一个文件夹中的一个符号链接(或脚本)在您的路径,那么它可以作为git all status
(等)。 它只支持原点/主,但它可以被编辑或与另一种方法相结合。
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
使用简单的正则表达式:
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
也许这个,如果你想添加任务,crontab中:
#!/bin/bash
dir="/path/to/root"
lock=/tmp/update.lock
msglog="/var/log/update.log"
log()
{
echo "$(date) ${1:-missing}" >> $msglog
}
if [ -f $lock ]; then
log "Already run, exiting..."
else
> $lock
git -C ~/$dir remote update &> /dev/null
checkgit=`git -C ~/$dir status`
if [[ ! "$checkgit" =~ "Your branch is up-to-date" ]]; then
log "-------------- Update ---------------"
git -C ~/$dir pull &>> $msglog
log "-------------------------------------"
fi
rm $lock
fi
exit 0
我用一个版本的基础上斯蒂芬·哈伯曼的回答脚本:
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
,它可以用一个可选的参数来调用directory name
本地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
它可以在这里为好。
读很多答案和多个职位,并且花费了半天时间尝试不同的排列组合后,这是我想出了。
如果您使用的是Windows,你可以运行使用的Git的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.
如果是打印由脚本的变化,那么你可以继续获取或拉。 该脚本可能不是有效的,但是它会为我做这项工作。
更新 - 二零一五年十月三十零日:标准错误到dev空防止印刷与密码到控制台的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
对于谁在这个问题上寻找这个最终的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')
}
您还可以找到一个Phing脚本现在谁做到这一点。
我需要一个解决方案来自动更新我的生产环境,我们非常高兴感谢这个脚本,我分享。
该脚本是用XML,需要Phing 。