“git pull --all”이 모든 로컬 브랜치를 업데이트 할 수 있습니까?


473

마스터, 스테이징 및 프로덕션과 같은 원격 브랜치가 3 개 이상있는 경우가 많습니다. 그 원격 지점을 추적하는 3 개의 로컬 지점이 있습니다.

내 모든 지사를 업데이트하는 것은 지루합니다.

git fetch --all
git rebase origin/master
git checkout staging
git rebase origin/staging
git checkout production
git rebase origin/production

"git pull-all"을 할 수 있기를 원하지만 작동시키지 못했습니다. "fetch --all"을 수행 한 다음 현재 작업 분기를 업데이트 (빨리 감기 또는 병합)하지만 다른 로컬 분기는 업데이트하지 않는 것 같습니다.

여전히 각 로컬 지점으로 수동 전환하고 업데이트하고 있습니다.


8
빠른 경우에만 로컬 추적 분기의 자동 업데이트를 원하십니까? Ypu는 합병으로 인해 해결해야 할 혼란이 생길 ​​수 있기 때문에 ...
Jakub Narębski

34
이 문제를 해결하기 위해 보수적 인 300 달러의 컨설팅 시간을 가정하면,이 단일 문제로 인해 회사의 조회수는 77,476 달러로 23,242,800 달러입니다. 이제이 질문 stackoverflow.com/questions/179123/… 및 다른 모든 질문을 고려하십시오 . 와.
Luke Puplett

16
@Luke 당신이 내가 들었던 첫 번째 사람은 git가 우리가 원하는 것을 회사가 돈을 버는 것을하도록 만드는 데 시간이 얼마나 걸 렸는지 지적했다. 이 간단한 것들은 자동이어야하고 너무 간단해야합니다. IMO 포럼을 읽기 위해 브라우저를 열 필요는 없습니다.
사무엘

13
@LukePuplett Mercurial에 비해 git에 대해 git에 대해 거의 ~ 9 배 많은 질문이 있으며, 전자의 대부분은 "git에서 <간단한 조작>을 어떻게 수행합니까?" 이것은 git이 잘못 설계되었거나 문서화가 잘못되었거나 직관적이지 않거나 세 가지 모두임을 나타냅니다.
이안 켐

26
@IanKemp 나는 SO의 인구 통계를 모른 채 그 주장을하는 것이 안전하다는 것을 확신하지 못합니다. Mercurial이 여기에서 일반적으로 사용되지 않거나 사용자가 다른 포럼을 사용하여 질문하는 경우 동일한 결과를 기대합니다. :) 어셈블리와 비교하여 Javascript에 대해 ~ 51 배 많은 질문이 있으므로 이러한 종류의 메트릭만으로 도구를 판단하는 것이 항상 정확한 것은 아닙니다.
danShumway

답변:


188

설명하는 동작 pull --all은 예상 한대로 정확하지만 반드시 유용한 것은 아닙니다. 이 옵션은 git fetch로 전달됩니다. 그러면 git fetch가 필요한 것 대신에 모든 리모컨에서 모든 참조를 가져옵니다. pull그런 다음 적절한 단일 분기를 병합합니다 (또는 경우에 따라 리베이스).

다른 지점을 확인하려면 해당 지점을 확인해야합니다. 그리고 그렇습니다. 병합 (및 rebasing)에는 절대적 으로 작업 트리가 필요하므로 다른 분기를 확인하지 않고는 작업 트리를 수행 할 수 없습니다. 원하는 경우 설명 된 단계를 스크립트 / 별명으로 마무리 할 수 ​​있습니다. 명령 &&중 하나가 실패 하더라도 쟁기질을 시도하지 않도록 명령을 결합하는 것이 좋습니다 .


2
명령 행의 예를 제시하면 투표하겠습니다. github 에이 문제가 있습니다. UI에서 분기를 만들었습니다. 이제 지점을 보여줄 현지인이 필요합니다. git pull --all; git branch ... argh ... 명령 : git branch -a
mariotti

@mariotti 당신이하려는 일에 달려 있으며, 당신의 의견에서 분명하지 않습니다. 새로운 질문을하는 것이 가장 좋습니다.
Cascabel

1
또는 @Jefromi .. 예를 들어보십시오. 나는 실제로 당신에게 동의했다.
mariotti

3
@mariotti이 답변의 요점은 기본 제공 명령이 실제로 OP가 요청한 것을 수행하지 않기 때문에 필요한 단계 순서가 필요하다는 것입니다. 이러한 단계를 자동화 할 수 있지만 (예 : John의 답변 참조) 반드시 수행해야합니다. 따라서 수행하려는 작업이 OP와 정확히 동일한 경우 실제로 제공 할 예가 없으며 다른 작업을 수행하려는 경우 새로운 질문을해야합니다. 이것이 StackOverflow의 작동 방식입니다! (귀하의 의견은 명확하지 않지만 최선의 추측은 여기서 OP와 다른 것을 원한다는 것입니다. 새로운 질문입니다.)
Cascabel

예, 다소 다릅니다. 그러나 귀하의 답변은 상황에 완벽했습니다. 그리고 나는 당신의 대답 때문에 더 이상 묻지 않아도 될 것입니다. 그냥 : 받아 들인 대답은 git-up을 사용합니다 .git-up은 단순히 git 명령 줄에 대한 인터페이스입니다. 몇 줄의 git 명령에서 명시 적으로 만들 수 있기를 바랍니다. 현재 답변은 git이 아닙니다.
mariotti

206

허브sync부속 명령 을 사용합니다 이를 자동화합니다. 내가 가진 alias git=hub내에서 .bash_profile명령 I 유형이 있으므로 :

git sync

업스트림 분기와 일치하는 모든 로컬 분기가 업데이트됩니다. 매뉴얼 페이지에서 :

  • 지역 지점이 구식 인 경우 빨리 감습니다.
  • 지역 지점에 압축되지 않은 작업이 포함되어 있으면 경고하십시오.
  • 분기가 병합 된 것으로 보이고 업스트림 분기가 삭제 된 경우 삭제하십시오.

또한 현재 브랜치에서 커밋되지 않은 변경 사항을 숨김 / 스 태싱 해제 처리합니다.

나는 git-up 이라는 비슷한 도구를 사용 했지만 더 이상 유지 관리 git sync되지 않으며 거의 ​​똑같은 일을합니다.


15
Windows는 어떻습니까?
Violet Giraffe

6
@ TrentonD.Adams 커밋 날짜와 작성자 날짜는 다른 개념입니다. 리베이스는 커밋 날짜를 변경하지만 작성자 날짜는 변경하지 않습니다 (작성자 날짜도 변경되는 충돌 제외). 작성자 날짜는 커밋 트리가 작성된시기를 나타내며 충돌하지 않는 리베이스 중에 변경해서는 안됩니다. rebase는 항상 새 커밋을 생성하므로 커밋 날짜가 변경됩니다. 따라서 커밋 날짜는 항상 올바른 순서입니다.
Dev

16
git-up의 자동 리베이스 동작을 끄려면을 실행하십시오 git config --global git-up.rebase.auto false.
Dan Loewenherz

18
@MaxYankov Rebasing 공유 히스토리는 일반적으로 피해야합니다. 풀 동안 로컬 커밋을 리베이스하는 데 아무런 문제가 없습니다.
Dev

23
로컬 커밋을 rebasing하면 기록을 다시 작성하고 실제로보다 간단하게 만듭니다. rebase를 사용하면 자동으로 병합되었지만 컴파일되지는 않지만 컴파일되지는 않지만 작동하지 않는 코드를 발견 할 수 있습니다. 병합은 작업 방식을 인정합니다. 다른 사람의 변경 사항을 통합하기 전에 변경 사항을 구현하고 테스트했으며 병합 커밋은 매우 유용한 시점입니다. 즉, 다른 차게 셋이 서로 잘 어울릴 수있는 곳입니다. Rebasing은이 과정이 결코 일어나지 않는 것처럼 보이게합니다. 이는 사실이 아니며 매우 위험한 관행입니다.
Max Yankov

39

나는이 질문이 거의 3 세라는 것을 알고 있지만, 나 자신에게도 같은 질문을하고 준비된 해결책을 찾지 못했습니다. 그래서 나는 사용자 정의 git 명령 쉘 스크립트를 스스로 만들었습니다.

여기가 간다 git-ffwd-update스크립트는 다음을 수행 ...

  1. git remote update늦은 개정을 가져 오기 위해 a 를 발행합니다.
  2. 그런 다음 git remote show원격 분기를 추적하는 로컬 분기 목록을 가져 오는 데 사용 합니다 (예 :와 함께 사용할 수있는 분기 git pull).
  3. 그런 다음 git rev-list --count <REMOTE_BRANCH>..<LOCAL_BRANCH>로컬 지점이 원격 뒤에있는 커밋 수를 확인합니다 (그리고 그 반대도 마찬가지)
  4. 로컬 분기 1 이상의 커밋 앞서의 경우, 그것은 할 수 없습니다 빠른 전달과 요구는 합병 또는 손으로 업데이트 할 수
  5. 로컬 브랜치가 0 커밋 앞서 있고 1 개 이상의 커밋이 뒤에 있다면 git branch -f <LOCAL_BRANCH> -t <REMOTE_BRANCH>

스크립트는 다음과 같이 호출 될 수 있습니다.

$ git ffwd-update
Fetching origin
 branch bigcouch was 10 commit(s) behind of origin/bigcouch. resetting local branch to remote
 branch develop was 3 commit(s) behind of origin/develop. resetting local branch to remote
 branch master is 6 commit(s) behind and 1 commit(s) ahead of origin/master. could not be fast-forwarded

전체 스크립트는로 저장해야하며에 있어야 git-ffwd-update합니다 PATH.

#!/bin/bash

main() {
  REMOTES="$@";
  if [ -z "$REMOTES" ]; then
    REMOTES=$(git remote);
  fi
  REMOTES=$(echo "$REMOTES" | xargs -n1 echo)
  CLB=$(git rev-parse --abbrev-ref HEAD);
  echo "$REMOTES" | while read REMOTE; do
    git remote update $REMOTE
    git remote show $REMOTE -n \
    | awk '/merges with remote/{print $5" "$1}' \
    | while read RB LB; do
      ARB="refs/remotes/$REMOTE/$RB";
      ALB="refs/heads/$LB";
      NBEHIND=$(( $(git rev-list --count $ALB..$ARB 2>/dev/null) +0));
      NAHEAD=$(( $(git rev-list --count $ARB..$ALB 2>/dev/null) +0));
      if [ "$NBEHIND" -gt 0 ]; then
        if [ "$NAHEAD" -gt 0 ]; then
          echo " branch $LB is $NBEHIND commit(s) behind and $NAHEAD commit(s) ahead of $REMOTE/$RB. could not be fast-forwarded";
        elif [ "$LB" = "$CLB" ]; then
          echo " branch $LB was $NBEHIND commit(s) behind of $REMOTE/$RB. fast-forward merge";
          git merge -q $ARB;
        else
          echo " branch $LB was $NBEHIND commit(s) behind of $REMOTE/$RB. resetting local branch to remote";
          git branch -f $LB -t $ARB >/dev/null;
        fi
      fi
    done
  done
}

main $@

1
이 스크립트에 감사드립니다. 누군가가 해당 스크립트를 Windows 배치로 변환 할 수 있습니까?
Saariko

@Saariko 왜 일반 Windows 쉘에서 git을 사용하고 싶지 않습니까? cygwin과 같은 것을 사용한다면이 스크립트는 잘 동작 할 것입니다 ... (내가 테스트하지는 않았지만)
muhqu

@RyanWilcox 덕분에, 나는 (근무일) 매일처럼 사용하고 있습니다 ... ;-) 더 많은 git 관련 스크립트 및 별칭에 대한 내 도트 파일을보고 싶을 수도 있습니다 : github.com/muhqu/dotfiles
muhqu

@muhqu 나는 당신의 스크립트를 사용하려고 노력하고 있는데 왜 그것이 처음으로 효과가 있었는지는 모르겠지만 지금은 "예상대로"작동하지 않습니다. 예를 들어 this을 살펴보십시오 . 스크립트를 실행 한 후에도 왜 여전히 마스터 78이 커밋됩니까?
BPL

1
@muhqu 최신 git 버전에서 -t와 -l은 한 번의 git branch호출 내에서 함께 사용되지 않아야합니다 . 호출을 변경하기 위해 -l을 제거하면 git branch -f $LB -t $ARB >/dev/null;스크립트가 정상적으로 작동합니다.
Radek Liska

24

자동화하기가 어렵지 않습니다.

#!/bin/sh
# Usage: fetchall.sh branch ...

set -x
git fetch --all
for branch in "$@"; do
    git checkout "$branch"      || exit 1
    git rebase "origin/$branch" || exit 1
done

4
스크립트에서 별칭을 사용하지 않는 것이 가장 좋습니다. 이것은 실제로 아무것도 가져 오지 않고 이미 가져온 콘텐츠를 리베이스합니다. 당신은 변경해야합니다 git rebase origin/$branch으로 git pull는 (아마도 원점에) 적절한 추적 지점에서 가져옵니다 그래서, 및 병합 또는 REBASE 중 하나는 설정에 의해 결정한다.
Cascabel

@Jefromi : 나는 잊었다 fetch. 편집했다; 추가 기능 / OP에 관계없이 무엇이든지 수정합니다.
프레드 푸

8
나는 여전히 당신이 pull(또는 check branch.<branch>.rebase) 사용하고 싶을 수도 있다고 생각 하므로 실수로 정상적으로 당겨 지도록 설정된 브랜치를 리베이스하지 마십시오 (병합).
Cascabel

1
첫 번째 오류에서 인터프리터를 종료 하는 set -e대신 사용하는 것이 좋습니다 || exit 1.
crishoj

18

옵션이 있기를 원하기 때문에 이것은 여전히 ​​자동적이지 않습니다-그리고 이것이 빨리 감기 업데이트에서만 발생할 수 있는지 확인해야합니다 (수동으로 풀을 수행하는 것이 훨씬 안전합니다 !!), 그러나 당신이 할 수있는주의 사항 :

git fetch origin
git update-ref refs/heads/other-branch origin/other-branch

체크 아웃하지 않고 로컬 지점의 위치를 ​​업데이트합니다.

참고 : 현재 지점 위치를 잃고 원점 지점으로 이동하면 병합해야 할 경우 데이터가 손실됩니다!


1
이것이 바로 내가 찾던 솔루션입니다. 나는 일반적으로 여러 지점에서 변경 사항을 풀지 않고 리모콘과 일치하도록 다양한 로컬 지점을 업데이트하려고합니다. 이 솔루션은 일반적인 삭제 / 재확인 방법보다 훨씬 좋습니다!
Dave Knight

1
하나의 명령으로 결합 :git fetch origin other-branch:other-branch
fabb

12

여기에는 많은 답변이 있지만 git-fetch로컬 참조를 직접 업데이트 하는 데 사용 하는 것은 없습니다 . 이것은 분기를 확인하는 것보다 훨씬 간단하고보다 안전합니다 git-update-ref.

여기서는 git-fetch비 현재 분기 및 현재 분기를 업데이트 하는 데 사용 합니다 git pull --ff-only. 그것:

  • 지점을 확인하지 않아도됩니다
  • 빨리 감기 할 수있는 경우에만 지점을 업데이트합니다.
  • 빨리 감을 수 없을 때보고합니다

그리고 여기 있습니다 :

#!/bin/bash
currentbranchref="$(git symbolic-ref HEAD 2>&-)"
git branch -r | grep -v ' -> ' | while read remotebranch
do
    # Split <remote>/<branch> into remote and branchref parts
    remote="${remotebranch%%/*}"
    branchref="refs/heads/${remotebranch#*/}"

    if [ "$branchref" == "$currentbranchref" ]
    then
        echo "Updating current branch $branchref from $remote..."
        git pull --ff-only
    else
        echo "Updating non-current ref $branchref from $remote..."
        git fetch "$remote" "$branchref:$branchref"
    fi
done

맨 페이지에서 git-fetch:

   <refspec>
       The format of a <refspec> parameter is an optional plus +, followed by the source ref <src>,
       followed by a colon :, followed by the destination ref <dst>.

       The remote ref that matches <src> is fetched, and if <dst> is not empty string, the local ref
       that matches it is fast-forwarded using <src>. If the optional plus + is used, the local ref is
       updated even if it does not result in a fast-forward update.

git fetch <remote> <ref>:<ref>(없이 +) 를 지정 하면 빨리 감기 할 수있을 때만 로컬 참조를 업데이트하는 인출을 얻습니다.

참고 : 로컬 및 원격 브랜치의 이름이 동일하고 모든 브랜치를 추적하려는 것으로 가정하면 실제로는 로컬 브랜치 및 추적하도록 설정 한 로컬 브랜치에 대한 정보를 사용해야합니다.


1
" 앞으로 빨리 갈 수있는 경우에만 분기를 업데이트합니다" -앞으로 빨리의 중요성은 무엇입니까? 모든 지점에서 최신 소스를 원할 경우 빠른 전달에 관심을 가져야하는 이유는 무엇입니까? 이와 같은 것들이 Git과 Fanboi 's를 비웃습니다. 하나의 명령으로이 작업을 수행 할 수 없습니다. 대신 몇 개의 반복 된 명령이 있고 분기 수인 c*n단계 (1 대신) 를 수행해야합니다 . cn
jww

@jww 세계에서 가장 많이 사용하는 VCS 일 때는 "Git과 그것의 Fanboi 's (웃음)을 비웃는 데 도움이되지 않습니다. 그러나 나는 틀렸다 ... 나는 이런 종류의 "전역 풀 (global pull)"스크립트의 맥락에서 현재 충돌하지 않는 분기를 변경하려고 시도하지 않는 것이 현명하다고 생각한다.
Ville

도움이되었습니다. 감사합니다. 내가 싫어하는 것은 모든 원격 지점 (관심없는 항목 포함)에 대해 로컬로 지점을 만들었으므로 이미 로컬에있는 지점으로 제한 하도록 변경 git branch -r | grep -v ' -> ' | while read remotebranch했습니다 git branch -r | grep -v ' -> ' | grep -f <(git branch | cut -c 3- | awk '{print "\\S*/"$0"$"}') | while read remotebranch. 또한 git fetch --prune시작하기 전에 무언가를 수행하기 전에 원격 지점 목록을 업데이트하기 위해를 추가하여 경고를 피했습니다.
Nate Cook

11

이 문제는 (아직) 스크립팅 없이는 아직 해결되지 않았습니다. Junio ​​C Hamano의 git 메일 링리스트에있는 이 게시물 을 참조 하여 상황을 설명하고 간단한 솔루션을 요청하십시오.

주요 이유는 다음이 필요하지 않다는 것입니다.

고대 버전 (즉, v1.5.0 이상)이 아닌 git을 사용하면 더 이상 원격을 완전히 추적하는 로컬 "dev"를 가질 이유가 없습니다. 보고 만보고 싶다면 " git checkout origin/dev" 를 사용하여 분리 된 HEAD에서 직접 원격 추적 분기를 확인할 수 있습니다 .

즉, 사용자가 편리하게 할 수있는 유일한 경우는 로컬 변경이 있거나 일부를 계획 할 때 원격 지점을 "추적"하는 로컬 지점을 처리하는 것입니다.

"dev"제거를 추적하도록 표시된 "dev"에 대한 로컬 변경 사항이 있고 "dev"와 다른 분기에있는 경우 " git fetch"가 원격 추적 "dev"를 업데이트 한 후에는 아무것도 수행하지 않아야 합니다. . 어쨌든 빨리 감지 않을 것입니다

해결책에 대한 요구는 요청 된 원래 포스터와 같이 빨리 감기를 통해 최신 분기를 유지하기보다는 현재 원격 추적 분기를 따르는 로컬 분기 를 제거 하는 옵션 또는 외부 스크립트가 필요했습니다.

git branch --prune --remote=<upstream>지역 분기를 반복 하는 " "는 어떻 습니까?

(1) 현재 지점이 아닙니다. 및
(2)에서 찍은 일부 지점을 추적하기 위해 표시되는 <상류>; 및
(3) 그 자체에 어떤 커밋이없는;

그런 다음 그 지점을 제거? " git remote --prune-local-forks <upstream>"도 괜찮습니다. 어떤 명령이 기능을 그렇게 많이 구현하는지는 중요하지 않습니다.

참고 : git 2.10부터는 그러한 해결책이 없습니다. 참고 그git remote prune부속 명령 및git fetch --prune더 이상하지 트랙 분기를 원격 추적하는 것이 지역 지점 (있는 원격 추적 지점 상류 지점입니다) 제거에 대한 원격에 존재하는 지점 원격 추적 브랜치를 제거하는 방법에 대한 없습니다.


링크 만 게시하는 대신 링크를 참조로 사용하여 실제 콘텐츠 게시하십시오. 그 링크는 이제 죽었습니다. 너무 나쁘고 유망한 소리. (이 답변은 2009 년 이후의 것으로 알고 있으므로 나중에 참조하기위한 참고 사항입니다.)
michael

고마워 (와 오랜 세월 후에 빠른 응답). 지금이 스레드는 "것을 볼 수 에 대한 호출 "내 원래의 오독에 반대하는 간단한 솔루션 ' 제공하는 간단한 솔루션을 ".
마이클

@ michael_n : 확장 ... 흠, 이제 게시물이 요청 된 솔루션에 관한 것이 아니라 문제에 관한 것임을 알았습니다 (XY 문제가 있다고 가정).
Jakub Narębski

흠, 헤드가 분리 된 상태에서 엿보기가 더 쉬워 져야합니다. 특히 유용한 정보를 상태에 표시하고 풀백 된 커밋과 같은 약간의 피드백으로 작업 공간을 빨리 감을 수 있습니다. 그런 다음 읽기 전용 로컬 분기를 대체합니다.
eckes

9

여기에는 충분한 대답이 있지만, 배관 중 일부는 시작하지 않은 사람에게는 약간 불투명 할 수 있습니다. 다음은 쉽게 사용자 정의 할 수있는 훨씬 간단한 예입니다.

$ cat ~/bin/git/git-update-all
#!/bin/bash
# Update all local branches, checking out each branch in succession.
# Eventually returns to the original branch. Use "-n" for dry-run.
git_update_all() {
  local run br
  br=$(git name-rev --name-only HEAD 2>/dev/null)
  [ "$1" = "-n" ] && shift && run=echo

  for x in $( git branch | cut -c3- ) ; do
     $run git checkout $x && $run git pull --ff-only || return 2
  done

  [ ${#br} -gt 0 ] && $run git checkout "$br"
}

git_update_all "$@"

당신이 추가하면 ~/bin/git당신에게 PATH(파일은 가정 ~/bin/git/git-update-all), 당신은 단지 실행할 수 있습니다 :

$ git update-all

감사! 당신은 ... 나에게 bash는 함께 연주의 시간을 저장
8ctopus을

5

Mac OS X 에서이 스크립트 를 추가하십시오 .profile.

# Usage:
#   `git-pull-all` to pull all your local branches from origin
#   `git-pull-all remote` to pull all your local branches from a named remote

function git-pull-all() {
    START=$(git symbolic-ref --short -q HEAD);
    for branch in $(git branch | sed 's/^.//'); do
        git checkout $branch;
        git pull ${1:-origin} $branch || break;
    done;
    git checkout $START;
};

function git-push-all() {
    git push --all ${1:-origin};
};

1
이렇게하면 모든 변경 사항을 먼저 숨기고 복원해야합니까?
Mel

5

좋은 대답은 다음과 같습니다. 모든 자식 분기를 가져 오는 방법

for remote in `git branch -r`; do git branch --track $remote; done
git pull --all

왜 할 제안하는 git fetchgit pull대신에, git pull?
syntagma

감사. pull은 모든 리모컨에서 모든 분기를 가져 오는 것 같습니다. 변경
milkovsky

8
이것은 모든 리모트를 가져 오지만 현재 브랜치 만 병합합니다. 리모컨이 10 개인 경우 각 리모컨을 수동으로 체크 아웃하고 병합해야합니다.
mpoisot

이렇게하면 로컬로 모든 원격 지점을 만듭니다 origin/접두사
야신 ElBadaoui

3

내가 GitBash를 위해 작성한 스크립트 . 다음을 수행합니다.

  • 기본적으로 원점을 추적하도록 설정된 모든 분기의 원점에서 가져 오기를 통해 원하는 경우 다른 리모콘을 지정할 수 있습니다.
  • 현재 브랜치가 더티 상태 인 경우 변경 사항을 숨기고 마지막에 이러한 변경 사항을 복원하려고 시도합니다.
  • 원격 지점을 추적하도록 설정된 각 로컬 지점에 대해 다음을 수행합니다.
    • git checkout branch
    • git pull origin
  • 마지막으로 원래 분기 및 복원 상태로 돌아갑니다.

** 나는 이것을 사용하지만 철저히 테스트하지는 않았으므로 자신의 책임하에 사용하십시오. 여기 .bash_alias 파일에서이 스크립트의 예를 참조 하십시오 .

    # Do a pull on all branches that are tracking a remote branches, will from origin by default.
    # If current branch is dirty, will stash changes and reply after pull.
    # Usage: pullall [remoteName]
    alias pullall=pullAll
    function pullAll (){
     # if -h then show help
     if [[ $1 == '-h' ]]
    then
      echo "Description: Pulls new changes from upstream on all branches that are tracking remotes."
      echo 
      echo "Usage: "
      echo "- Default: pullall"
      echo "- Specify upstream to pull from: pullall [upstreamName]"
      echo "- Help: pull-all -h"
    else

     # default remote to origin
     remote="origin"
     if [ $1 != "" ]
     then
       remote=$1
     fi

     # list all branches that are tracking remote
     # git branch -vv : list branches with their upstreams
     # grep origin : keep only items that have upstream of origin
     # sed "s/^.."... : remove leading *
     # sed "s/^"..... : remove leading white spaces
     # cut -d" "..... : cut on spaces, take first item
     # cut -d splits on space, -f1 grabs first item
     branches=($(git branch -vv | grep $remote | sed "s/^[ *]*//" | sed "s/^[ /t]*//" | cut -d" " -f1))

     # get starting branch name
     startingBranch=$(git rev-parse --abbrev-ref HEAD)

     # get starting stash size
     startingStashSize=$(git stash list | wc -l)

     echo "Saving starting branch state: $startingBranch"
     git stash

     # get the new stash size
     newStashSize=$(git stash list | wc -l)

     # for each branch in the array of remote tracking branches
     for branch in ${branches[*]}
     do
       echo "Switching to $branch"
       git checkout $branch

       echo "Pulling $remote"
       git pull $remote

     done

     echo "Switching back to $startingBranch"
     git checkout $startingBranch

     # compare before and after stash size to see if anything was stashed
     if [ "$startingStashSize" -lt "$newStashSize" ]
     then
       echo "Restoring branch state"
       git stash pop
     fi
    fi
    }

동등한 Windows bat 파일을 제공 할 수 있습니까?
Jaffy

1
@Jaffy 내가 얼마나 많은 시간을 가지고 있는지 잘 모르겠고 배치에 능숙하지는 않지만 그것을 줄 수는 있습니다. 여기에 내 진도를 게시 할 것입니다. 다른 사람들이 개입하여 도울 수 있습니까?
philosowaffle


3

업데이트 된 답변을 게시하기 만하면됩니다. git-up더 이상 유지 관리되지 않으며 설명서를 읽으면 git에서 기능을 사용할 수 있다고 언급합니다 .

Git 2.9에서 git pull --rebase --autostash는 기본적으로 동일한 기능을 수행합니다.

따라서 Git 2.9 이상으로 업데이트하면 git-up을 설치하는 대신이 별칭을 사용할 수 있습니다.

git config --global alias.up 'pull --rebase --autostash'

당신은 또한 git pullGit 2.9에서 이것을 설정할 수 있습니다 (@VonC 덕분에 그의 대답을 참조 하십시오 )

git config --global pull.rebase true
git config --global rebase.autoStash true

1
별칭이 필요하지 않습니다. 올바른 설정으로 간단한 git pull이면 충분합니다. stackoverflow.com/a/40067353/6309
VonC

위대한 전화 덕분에 밖으로 @VonC 내 대답을 업데이트 :) 또한에 PR를 제출할 수 git-up그들이 그 언급하지 않기 때문에 문서
8월

이것은 모든 로컬 브랜치를 한 번에 업데이트하지는 않기 때문에 주로 사용했습니다 git-up.
ray

설명서 업데이트 git-up:)
aug

3

이 질문과 같은 문제가 발생했습니다 ...

나 자신에 대해 궁금해해서 .bashrc파일 내에서 작은 별칭 기능을 수행했습니다 .

gitPullAll() {
    for branch in `git branch | sed -E 's/^\*/ /' | awk '{print $1}'`; do
        git checkout $branch
        git pull -p
        printf "\n"
    done
    echo "Done"
}

나를 위해 일했습니다 (:


2

경우 심판은 / 헤드는 / 마스터가 로 빠르게 전달할 수 있습니다 심판 / 리모트는 / foo는 / 마스터 의 출력

git merge-base refs/heads/master refs/remotes/foo/master

참조 / 헤드 / 마스터 인 SHA1 ID를 반환해야합니다. 가리키는 합니다. 이를 통해 전환 커밋이 적용되지 않은 모든 로컬 분기를 자동으로 업데이트하는 스크립트를 구성 할 수 있습니다.

이 작은 쉘 스크립트 ( git-can-ff 라고 함 )는 어떻게 수행 할 수 있는지 보여줍니다.

#!/bin/sh

set -x

usage() {
    echo "usage: $(basename $0) <from-ref> <to-ref>" >&2
    exit 2
}

[ $# -ne 2 ] && usage

FROM_REF=$1
TO_REF=$2

FROM_HASH=$(git show-ref --hash $FROM_REF)
TO_HASH=$(git show-ref --hash $TO_REF)
BASE_HASH=$(git merge-base $FROM_REF $TO_REF)

if [ "$BASE_HASH" = "$FROM_HASH" -o \
     "$BASE_HASH" = "$FROM_REF" ]; then
    exit 0
else
    exit 1
fi

그 의견에서 무엇을 의미합니까?
hillu

나는 힐 루가 제안한 스크립트를 작성할 수 없으며 git-merge-base를 사용할 git 지식이 충분하지 않다고 확신합니다.
Norman Ramsey

2
나는 친절하게 제공된 스크립트를 악용하기에 충분히 모델을 이해하지 못합니다. 사람을 수은으로 바꾸는 것으로 충분합니다.
Norman Ramsey

나는 개인적으로 Tommi Virtanen의 기사 "컴퓨터 과학자들을위한 Git"이 git의 모델과 용어에 익숙해지는 데 매우 도움이된다는 것을 알게되었다.
hillu

2

Matt Connolly의 답변을 완성하려면 분기를 체크 아웃하지 않고 빨리 전달할 수있는 로컬 분기 참조를 업데이트하는 것이보다 안전한 방법입니다. 빨리 감을 수없는 분기 (즉 분기 된 분기)는 업데이트하지 않으며 현재 체크 아웃 된 분기 (업그레이드 사본도 업데이트해야하기 때문에)를 업데이트하지 않습니다.

git fetch

head="$(git symbolic-ref HEAD)"
git for-each-ref --format="%(refname) %(upstream)" refs/heads | while read ref up; do
    if [ -n "$up" -a "$ref" != "$head" ]; then
        mine="$(git rev-parse "$ref")"
        theirs="$(git rev-parse "$up")"
        base="$(git merge-base "$ref" "$up")"
        if [ "$mine" != "$theirs" -a "$mine" == "$base" ]; then
            git update-ref "$ref" "$theirs"
        fi
    fi
done

2

이름이 빠른 지점 만 업스트림 지점과 일치하는 약간 다른 스크립트입니다. 또한 빨리 감기가 가능한 경우 현재 분기를 업데이트합니다.

을 실행하여 모든 지점의 업스트림 지점을 올바르게 설정했는지 확인하십시오 git branch -vv. 업스트림 지점을 설정하여git branch -u origin/yourbanchname

파일과 chmod 755에 복사하여 붙여 넣기 :

#!/bin/sh

curbranch=$(git rev-parse --abbrev-ref HEAD)

for branch in $(git for-each-ref refs/heads --format="%(refname:short)"); do
        upbranch=$(git config --get branch.$branch.merge | sed 's:refs/heads/::');
        if [ "$branch" = "$upbranch" ]; then
                if [ "$branch" = "$curbranch" ]; then
                        echo Fast forwarding current branch $curbranch
                        git merge --ff-only origin/$upbranch
                else
                        echo Fast forwarding $branch with origin/$upbranch
                        git fetch . origin/$upbranch:$branch
                fi
        fi
done;

2

다음 한 줄은 가능한 경우 업스트림 분기가있는 모든 분기를 빨리 감고 그렇지 않으면 오류를 인쇄합니다.

git branch \
  --format "%(if)%(upstream:short)%(then)git push . %(upstream:short):%(refname:short)%(end)" |
  sh

어떻게 작동합니까?

git branch명령 과 함께 사용자 정의 형식을 사용합니다 . 업스트림 분기가있는 각 분기에 대해 다음 패턴으로 선을 인쇄합니다.

git push . <remote-ref>:<branch>

이것은 sh브랜치 이름이 올바른 것으로 가정 하여 직접 파이프 될 수 있습니다 . | sh무엇을하고 있는지 보려면 생략 하십시오.

경고

원 라이너는 리모컨에 닿지 않습니다. 발행 git fetch또는git fetch --all 실행하기 전에.

현재 체크 아웃 한 지점은 다음과 같은 메시지로 업데이트되지 않습니다

! [remote rejected] origin/master -> master (branch is currently checked out)

이를 위해 정기적으로 의지 할 수 있습니다 git pull --ff-only .

별명

이 명령 .gitconfiggit fft수행 할 수 있도록 다음을 추가하십시오 .

[alias]
        fft = !sh -c 'git branch --format \"%(if)%(upstream:short)%(then)git push . %(upstream:short):%(refname:short)%(end)\" | sh' -

내도 참조하십시오 .gitconfig. 별칭은 "빨리 감기 추적 (분기)"의 약어입니다.


이것은 좋은 해결책이지만 @John hub제안 한 soluction을 사용 하여 더 나은 결과를 얻을 것이라고 생각 합니다.
Didier L

이것은 빠르고 간단하며 실제로 작동합니다! 나는 git push그것이 당신이 기대하는 것과 완전히 반대이기 때문에 당황 합니다. 비밀은 무엇입니까?
BrandonLWhite

@ BrandonLWhite : 나는 질문을 이해하지 못한다. 무엇을 기대 git push하십니까?
krlmlr

git push업로드 의미가 있습니다-로컬로 커밋을하고 업스트림으로 보내려고합니다. git pull다운로드 의미가 있습니다-로컬 브랜치에 업스트림 원격 커밋을 가져오고 싶습니다. 우리는 원격에서 로컬로 새로운 커밋을 다운로드하는 것에 대해 이야기하고 있기 때문에 git pull분명한 선택입니다. 그러나 아니요,이 트릭은을 사용합니다 git push. git push로컬 지점으로 원격 변경을 가져 오려면 어떻게해야합니까 ?!
BrandonLWhite

git push빠른 업데이트 인 경우 로컬 분기를 업데이트하는 데에도 사용할 수 있습니다.
krlmlr

1

@larsmans의 스크립트는 약간 개선되었습니다.

#!/bin/sh

set -x
CURRENT=`git rev-parse --abbrev-ref HEAD`
git fetch --all
for branch in "$@"; do
  if ["$branch" -ne "$CURRENT"]; then
    git checkout "$branch" || exit 1
    git rebase "origin/$branch" || exit 1
  fi
done
git checkout "$CURRENT" || exit 1
git rebase "origin/$CURRENT" || exit 1

완료되면 동일한 브랜치 에서 작업 사본을 체크 아웃합니다. 스크립트를 호출하기 전과 .

git pull버전 :

#!/bin/sh

set -x
CURRENT=`git rev-parse --abbrev-ref HEAD`
git fetch --all
for branch in "$@"; do
  if ["$branch" -ne "$CURRENT"]; then
    git checkout "$branch" || exit 1
    git pull || exit 1
  fi
done
git checkout "$CURRENT" || exit 1
git pull || exit 1

1

다른 많은 사람들이 비슷한 솔루션을 제공 한 것처럼 보이지만, 내가 생각 해낸 내용을 공유하고 다른 사람들이 참여하도록 초대 할 것이라고 생각했습니다. 이 솔루션은 멋진 다채로운 출력을 가지며 현재 작업 디렉토리를 정상적으로 처리하며 체크 아웃을 수행하지 않기 때문에 빠르며 작업 디렉토리를 그대로 둡니다. 또한 git 이외의 종속성이없는 쉘 스크립트 일뿐입니다. (지금까지 OSX에서만 테스트)

#!/usr/bin/env bash

gitup(){    
RED='\033[33;31m'
YELLO='\033[33;33m'
GREEN='\033[33;32m'
NC='\033[0m' # No Color

HEAD=$(git rev-parse HEAD)
CHANGED=$(git status --porcelain | wc -l)

echo "Fetching..."
git fetch --all --prune &>/dev/null
for branch in `git for-each-ref --format='%(refname:short)' refs/heads`; do

    LOCAL=$(git rev-parse --quiet --verify $branch)
    if [ "$HEAD" = "$LOCAL" ] && [ $CHANGED -gt 0 ]; then
        echo -e "${YELLO}WORKING${NC}\t\t$branch"
    elif git rev-parse --verify --quiet $branch@{u}&>/dev/null; then
        REMOTE=$(git rev-parse --quiet --verify $branch@{u})
        BASE=$(git merge-base $branch $branch@{u})

        if [ "$LOCAL" = "$REMOTE" ]; then
           echo -e "${GREEN}OK${NC}\t\t$branch" 
        elif [ "$LOCAL" = "$BASE" ]; then
            if [ "$HEAD" = "$LOCAL" ]; then
                git merge $REMOTE&>/dev/null
            else
                git branch -f $branch $REMOTE
            fi
            echo -e "${GREEN}UPDATED${NC}\t\t$branch"
        elif [ "$REMOTE" = "$BASE" ]; then
            echo -e "${RED}AHEAD${NC}\t\t$branch"
        else
            echo -e "${RED}DIVERGED${NC}\t\t$branch"
        fi
    else
        echo -e "${RED}NO REMOTE${NC}\t$branch"
    fi
done
}

https://github.com/davestimpert/gitup

죄송합니다. 위의 다른 도구와 동일한 이름을 가진 것 같습니다.


2
당신은 이것을 쓴 사람입니까? 그렇다면 귀하의 소속을 공개하십시오. 예를 들어 귀하와의 관계를 알려주십시오. 자세한 내용은 여기 를 참조하십시오. 구체적으로 말하지 마-쇼! ; 스크립트의 어떤 부분과 문제를 해결하는 방법 / 이유를 알려주십시오.
Keale

1
예, 썼습니다. 빠른 복사를 위해 위의 소스를 .bashrc 또는 .zshrc에 포함 시켰습니다.
Stimp

이것은 좋은 해결책이며 잘 작동합니다. 아무도 통지하지 않았다?
Ville

1

아래 스크립트를 사용하여 수행 할 수 있습니다 ... 먼저 모든 분기를 가져오고 하나씩 체크 아웃하고 자체적으로 업데이트합니다.

#!/bin/bash
git branch -r | grep -v '\->' | while read remote; do git branch --track 
"${remote#origin/}" "$remote"; done

set -x
CURRENT=`git rev-parse --abbrev-ref HEAD`
git fetch --all
branch_name=$(git branch | awk '{print $1" "}' | grep -v '*' | xargs)
for branch in $branch_name; do
   git checkout "$branch" || exit 1
   git rebase "origin/$branch" || exit 1
   git pull origin $branch|| exit 1
done
git checkout "$CURRENT" || exit 1
git pull || exit 1

답변 점수 매기기에 대한 설명 추가
fool-dev

1

하나의 git 명령으로 수행 할 수는 없지만 하나의 bash 줄로 자동화 할 수 있습니다.

한 줄로 모든 지점을 안전하게 업데이트하려면 다음과 같이하십시오.

git fetch --all && for branch in $(git branch | sed '/*/{$q;h;d};$G' | tr -d '*') ; do git checkout $branch && git merge --ff-only || break ; done
  • 하나의 분기를 빨리 감을 수 없거나 오류가 발생하면 제어를 다시 수행하고 수동으로 병합 할 수 있도록 중지하고 해당 분기에 남겨 둡니다.

  • 모든 지점을 빨리 감을 수 있다면 현재 있던 지점으로 끝나고 업데이트하기 전의 위치를 ​​떠나게됩니다.

설명 :

가독성을 높이기 위해 여러 줄로 나눌 수 있습니다.

git fetch --all && \
for branch in $(git branch | sed '/*/{$q;h;d};$G' | tr -d '*')
    do git checkout $branch && \
    git merge --ff-only || break
done
  1. git fetch --all && ... => 모든 리모컨에서 모든 참조를 가져오고 오류가 없으면 다음 명령을 계속합니다.

  2. git branch | sed '/*/{$q;h;d};$G' | tr -d '*'=>의 출력으로부터 git branch, sed으로 라인을 *상기 단부 (그래서 현재 브랜치 마지막으로 갱신 될 것이다)로 이동한다. 그런 tr다음를 제거하십시오 *.

  3. for branch in $(...) ; do git checkout $branch && git merge --ff-only || break ; done=> 이전 명령에서 얻은 각 분기 이름에 대해이 분기를 체크 아웃하고 빨리 감기와 병합하십시오. 실패하면 break이 호출되고 명령이 여기서 중지됩니다.

물론, 당신은 대체 할 수 git merge --ff-only와 함께 git rebase당신이 원하는 경우.

마지막으로 bashrc 에 별명으로 넣을 수 있습니다 .

alias git-pull-all='git fetch --all && for branch in $(git branch | sed '\''/*/{$q;h;d};$G'\'' | tr -d "*") ; do git checkout $branch && git merge --ff-only || break ; done'

또는 '와'를 엉망으로 만들거나 편집기에서 구문 가독성을 유지하는 것을 선호하는 경우 함수로 선언 할 수 있습니다.

git-pull-all()
{
    git fetch --all && for branch in $(git branch | sed '/*/{$q;h;d};$G' | tr -d '*') ; do git checkout $branch && git merge --ff-only || break ; done
}

보너스:

sed '/*/{$q;h;d};$G'부분 에 대한 설명을 원하는 사람들을 위해 :

  • /*/=>로 줄을 검색하십시오 *.

  • {$q => 마지막 줄에 있으면 종료합니다 (현재 분기가 이미 목록의 마지막 분기이므로 아무 것도 할 필요가 없습니다).

  • ;h;d} => 그렇지 않으면, 보류 버퍼에 행을 저장하고 현재 목록 위치에서 삭제하십시오.

  • ;$G => 마지막 행에 도달하면 보류 버퍼의 내용을 추가하십시오.


끝없는 줄의 모든 미친 것을 피하고 스크립트 상단 &&에 설정 set -e하여.
mcepl

0

“git pull --all”이 모든 로컬 브랜치를 업데이트 할 수 있습니까?

아닙니다. 빨리 감기를 위해 작은 도구를 작성했습니다. https://github.com/changyuheng/git-fast-forward-all

이 도구의 장점 :

  1. 하나의 저장소에서 여러 리모컨을 지원합니다. (hub sync 순간에 여러 개의 리모컨을 지원하지 않습니다.)
  2. 로컬 지점과 해당 원격 추적 지점에서 서로 다른 이름을 지원합니다.
  3. 모든 단일 브랜치에 대해 원격을 가져 오는 다른 스크립트보다 훨씬 빠릅니다.
  4. 오류가 발생하기 쉬운 정규식 구문 분석 / 편집이 없습니다.

1
를 사용하여 네트워크에 충돌하지 않도록 할 수 있습니다 git fetch . refspec. 는 .현재 저장소에서 대신 원격 하나에서 가져 말한다.
hugomg

-1

자식 2.9부터 :

git pull --rebase --autostash

참조 https://git-scm.com/docs/git-rebase를

작업을 시작하기 전에 임시 숨김을 자동으로 생성하고 작업이 끝난 후 적용합니다. 이는 더티 작업 트리에서 리베이스를 실행할 수 있음을 의미합니다. 그러나주의해서 사용하십시오. 리베이스에 성공한 후 마지막 숨김 응용 프로그램은 사소한 충돌을 초래할 수 있습니다.


-1

실제로 git 사용 version 1.8.3.1하면 다음과 같이 작동합니다.

[root@test test]# git br
* master
  release/0.1
  update
[root@test test]# git pull --rebase
remote: Enumerating objects: 9, done.
remote: Counting objects: 100% (9/9), done.
remote: Compressing objects: 100% (9/9), done.
remote: Total 9 (delta 2), reused 0 (delta 0)
Unpacking objects: 100% (9/9), done.
From http://xxx/scm/csdx/test-git
   d32ca6d..2caa393  release/0.1 -> origin/release/0.1
Current branch master is up to date.
[root@test test]# git --version
git version 1.8.3.1

마스터 지점에서 다른 모든 지점을 업데이트 할 수 있습니다. C

2.17 (사용중인)에서 어떤 버전이 고장 나거나 수정했는지 알 수 없습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.