힘내에서 풀이 필요한지 확인
원격 저장소가 변경되어 가져와야하는지 어떻게 확인합니까?
이제이 간단한 스크립트를 사용합니다.
git pull --dry-run | grep -q -v 'Already up-to-date.' && changed=1
그러나 그것은 다소 무겁습니다.
더 좋은 방법이 있습니까? 이상적인 솔루션은 모든 원격 분기를 확인하고 변경된 분기의 이름과 각 분기의 새 커밋 수를 반환하는 것입니다.
먼저를 사용 git remote update
하여 원격 참조를 최신 상태로 가져옵니다. 그런 다음 다음과 같은 몇 가지 작업 중 하나를 수행 할 수 있습니다.
git status -uno
추적중인 지점이 앞, 뒤 또는 분기되었는지 여부를 알려줍니다. 아무 것도 표시되지 않으면 로컬과 원격이 동일합니다.git show-branch *master
이름이 'master'(예 : master 및 origin / master )로 끝나는 모든 브랜치의 커밋을 보여줍니다 .
( ) -v
와 함께 사용 하면 어떤 브랜치가 업데이트되었는지 확인할 수 있으므로 추가 명령이 필요하지 않습니다.git remote update
git remote -v update
그러나 스크립트 또는 프로그램에서이 작업을 수행하고 결국 참 / 거짓 값으로 끝나는 것처럼 보입니다. 그렇다면 현재 HEAD 커밋과 추적중인 브랜치의 헤드 간의 관계를 확인할 수있는 방법 이 있습니다. 네 가지 가능한 결과가 있기 때문에 예 / 아니요 대답으로 줄일 수는 없습니다. 그러나 만약 당신이 a pull --rebase
를 할 준비가 되었다면 "local is behind"와 "local has diverged"를 "need to pull"로, 나머지 두개는 "do n't need to pull"로 취급 할 수 있습니다.
를 사용하여 모든 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
참고 : 이전 버전의 git은 @
자체적으로 허용되지 않았으므로 @{0}
대신 사용해야 할 수도 있습니다 .
UPSTREAM=${1:-'@{u}'}
현재 분기에 대해 구성된 원격 분기와 다른 원격 분기에 대해 확인하려는 경우이 라인을 사용하여 선택적으로 업스트림 분기를 명시 적으로 전달할 수 있습니다. 이것은 일반적으로 remotename / 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
병합 할 내용이 없습니다.
이것은 Git에서 기억 origin/master
하는 업스트림 브랜치 를 암시 적으로 사용하는 대신 명시 적으로 참조하는 경우 추적 원격이없는 기능 브랜치에있는 경우에도 작동 합니다.
스크립트 용인 경우 다음을 사용할 수 있습니다.
git fetch
$(git rev-parse HEAD) == $(git rev-parse @{u})
(참고 :이 답변과 이전 답변의 이점은 현재 분기 이름을 가져 오기 위해 별도의 명령이 필요하지 않다는 것입니다. "HEAD"및 "@ {u}"(현재 분기의 업스트림))가 처리합니다. 참조 자세한 내용은 "git rev-parse --help"를 참조하십시오.)
명령
git ls-remote origin -h refs/heads/master
원격의 현재 헤드를 나열합니다. 이전 값과 비교하거나 로컬 저장소에 SHA가 있는지 확인할 수 있습니다.
다음은 현재 브랜치의 HEAD 커밋 해시를 원격 업스트림 브랜치와 비교하는 Bash 한 줄입니다. 무겁 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)
Bash 명령 대체 구문을 사용하여 그룹화되고 중첩됩니다 . git rev-parse --abbrev-ref @{u}
축약 된 업스트림 참조 (예 :)를 반환 한origin/master
다음 파이프sed
명령에 의해 공백으로 구분 된 필드로 변환됩니다 (예 :)origin master
.- 이 문자열은
git ls-remote
원격 분기의 헤드 커밋을 반환하는 입력됩니다 . 이 명령은 원격 저장소와 통신합니다. 파이프cut
명령은 첫 번째 필드 (커밋 해시) 만 추출하여 탭으로 구분 된 참조 문자열을 제거합니다. git rev-parse HEAD
로컬 커밋 해시를 반환합니다.- Bash 구문
[ a = b ] && x || y
은 한 줄짜리를 완성합니다. 이것은 테스트 구문 내에서 Bash 문자열 비교 이며 그 뒤에 and-list 및 or-list 구문이 있습니다.=
[ test ]
&& 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
이를 수행하는 가장 좋은 방법은 다음과 같습니다.
git diff remotes/origin/HEAD
이 refspec을 등록했다고 가정합니다. 리포지토리를 복제했다면, 그렇지 않으면 (즉, 리포지토리가 로컬에서 새로 만들어지고 원격으로 푸시 된 경우) 명시 적으로 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
나는 brool이 제안한 방식으로 할 것입니다. 다음 한 줄 스크립트는 마지막으로 커밋 된 버전의 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 Berger가 제공했습니다. 정말 감사합니다. 모두가 이것을 필요로하고 모두가 댓글에서 이것을 놓칩니다. 따라서 여기에 어려움을 겪는 모든 사람에게 정답이 있습니다.이 명령의 출력을 사용하여 git pull을 수행해야하는지 알 수 있습니다. 출력이 0이면 분명히 업데이트 할 것이 없습니다.
@stackoverflow,이 사람에게 종을 줘. 감사합니다 @ Jake Berger
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
풀 필요 및 푸시 필요와 같은 일반적인 상황을 구분할 수 있으며 다중 스레드이므로 가져 오기가 한 번에 발생합니다. pull 및 status와 같은 여러 명령이 있습니다.
경로의 폴더에 심볼릭 링크 (또는 스크립트)를 넣으면 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
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
Assuming this script is called git-fetch-and-rebase
, it can be invoked with an optional argument directory name
of the local Git repository to perform operation on. If the script is called with no arguments, it assumes the current directory to be part of the Git repository.
Examples:
# 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
It is available here as well.
After reading many answers and multiple posts, and spending half a day trying various permutations, this is what I have come up with.
If you are on Windows, you may run this script in Windows using Git Bash provided by Git for Windows (installation or portable).
This script requires arguments
- 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
The script will
- Find the current branch
- Get the SHA1 of the remote on that branch
- Get the SHA1 of the local on that branch
- Compare them.
If there is a change as printed by the script, then you may proceed to fetch or pull. The script may not be efficient, but it gets the job done for me.
Update - 2015-10-30: stderr to dev null to prevent printing the URL with the password to the console.
#!/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
For the windows users who end up on this question looking for this, I've modified some of the answer into a powershell script. Tweak as necessary, save to a .ps1
file and run on demand or scheduled if you like.
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')
}
All such complex sugestions while the solution is so short and easy:
#!/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`
if [ $LAST_COMMIT != $LAST_UPDATE ]; then
echo "Updating your branch $BRANCH"
git pull --no-edit
else
echo "No updates available"
fi
You can also find a Phing script who does that now.
프로덕션 환경을 자동으로 업데이트하는 솔루션이 필요했고 공유하고있는이 스크립트 덕분에 매우 기쁩니다.
스크립트는 XML로 작성되었으며 Phing이 필요 합니다 .
참고 URL : https://stackoverflow.com/questions/3258243/check-if-pull-needed-in-git
'Programing' 카테고리의 다른 글
함수를 C에서 매개 변수로 어떻게 전달합니까? (0) | 2020.10.04 |
---|---|
데이터베이스 항목에 대한 소스 제어를 사용합니까? (0) | 2020.10.03 |
MySQL에서 새 사용자를 만들고 하나의 데이터베이스에 대한 전체 액세스 권한을 부여합니다. (0) | 2020.10.03 |
Java에서 YYYY-MM-DD HH : MI : Sec.Millisecond 형식으로 현재 시간을 얻는 방법은 무엇입니까? (0) | 2020.10.03 |
확인없이 cp를 강제로 덮어 쓰는 방법 (0) | 2020.10.03 |