“ 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" แต่ฉันก็ไม่สามารถทำให้มันทำงานได้ ดูเหมือนว่าจะ "ดึงข้อมูล - ทั้งหมด" จากนั้นอัปเดต (กรอไปข้างหน้าหรือผสาน) สาขาการทำงานปัจจุบัน แต่ไม่ใช่สาขาท้องถิ่นอื่น ๆ

ฉันยังคงติดสลับไปยังแต่ละสาขาในพื้นที่และอัปเดตด้วยตนเอง


8
คุณต้องการอัพเดทสาขาการติดตามอัตโนมัติในกรณีส่งต่ออย่างรวดเร็วหรือไม่? ypu ควรผสาน becaue สามารถมี conflicst คุณจะต้องแก้ไข ...
ยาคุบบNarębski

34
สมมติว่ามีค่าใช้จ่าย $ 300 ในการให้คำปรึกษาในการจัดการกับปัญหานี้ปัญหาเดียวนี้ทำให้ บริษัท มีค่าใช้จ่าย $ 23,242,800 โดยใช้จำนวนการดู 77,476 ครั้ง ตอนนี้ให้พิจารณาคำถามนี้stackoverflow.com/questions/179123/…และคำถามอื่น ๆ ทั้งหมด ว้าว.
Luke Puplett

16
@ ลุคคุณเป็นคนแรกที่ฉันได้ยินชี้ให้เห็นว่าเวลาที่ใช้ในการพยายามทำคอมไพล์ทำในสิ่งที่เราต้องการให้ บริษัท ต้นทุนเงิน สิ่งง่าย ๆ เหล่านี้ควรเป็นไปโดยอัตโนมัติและควรจะง่ายมากฉันไม่จำเป็นต้องเปิดเบราว์เซอร์เพื่ออ่านฟอรัม IMO
ซามูเอล

13
@LukePuplett มีคำถามเกี่ยวกับคอมไพล์ใน SO มากกว่า Mercurial เกือบ 9 เท่าและในอดีตคนส่วนใหญ่ดูเหมือนจะเป็น "ฉันจะทำ <simple operation> in git ได้อย่างไร? นั่นบ่งชี้ว่าคอมไพล์ถูกออกแบบมาไม่ดีเอกสารไม่ดีใช้งานไม่ได้หรือทั้งสามอย่าง
Ian Kemp

26
@IanKemp ฉันไม่แน่ใจว่าปลอดภัยที่จะทำการอ้างสิทธิ์โดยไม่ทราบถึงข้อมูลประชากรของ SO ถ้า Mercurial นั้นไม่ได้ใช้กันทั่วไปที่นี่หรือถ้าผู้ใช้งานใช้ฟอรัมอื่นเพื่อถามเกี่ยวกับมันฉันก็คาดหวังว่าจะเห็นผลลัพธ์เดียวกัน :) มีจำนวนคำถามเกี่ยวกับ Javascript มากกว่า 51 ครั้งเมื่อเทียบกับชุดประกอบดังนั้นอาจไม่แม่นยำเสมอไปที่จะตัดสินเครื่องมือโดยใช้ตัวชี้วัดเหล่านี้
danShumway

คำตอบ:


188

พฤติกรรมที่คุณอธิบายpull --allนั้นตรงตามที่คาดหวัง แต่ก็ไม่จำเป็นว่าจะมีประโยชน์ ตัวเลือกจะถูกส่งผ่านไปยังการเรียก git ซึ่งจะดึงการอ้างอิงทั้งหมดจากรีโมททั้งหมดแทนที่จะเป็นแค่ที่จำเป็น pullจากนั้นผสาน (หรือในกรณีของคุณ rebases) สาขาเดียวที่เหมาะสม

หากคุณต้องการตรวจสอบสาขาอื่นคุณจะต้องตรวจสอบพวกเขา และใช่ผสาน (และ rebasing) อย่างต้องใช้ต้นไม้ในการทำงานเพื่อให้พวกเขาไม่สามารถทำได้โดยไม่ต้องตรวจสอบจากสาขาอื่น ๆ คุณสามารถสรุปขั้นตอนที่อธิบายไว้ในสคริปต์ / นามแฝงได้หากต้องการ แต่ฉันขอแนะนำให้เข้าร่วมคำสั่งด้วย&&ดังนั้นหากหนึ่งในนั้นล้มเหลวมันจะไม่พยายามไถ


2
หากคุณให้ตัวอย่างบรรทัดคำสั่งฉันจะลงคะแนน ฉันมีปัญหานี้กับ GitHub ฉันสร้างสาขาบน UI ตอนนี้ฉันต้องการคนในท้องถิ่นของฉันเพื่อแสดงสาขา git pull - ทั้งหมด; git branch ... argh ... คำสั่ง: git branch -a
mariotti

@mariotti ขึ้นอยู่กับสิ่งที่คุณพยายามทำและยังไม่ชัดเจนจากความคิดเห็นของคุณ คุณอาจถามคำถามใหม่ได้ดีที่สุด
Cascabel

1
หรือ @Jefromi .. ยกตัวอย่าง ที่จริงฉันเห็นด้วยกับคุณ
mariotti

3
@mariotti จุดสำคัญของคำตอบนี้คือคำสั่งในตัวไม่ได้ทำตามที่ OP ร้องขอจริง ๆ ดังนั้นลำดับขั้นตอนที่จำเป็นต้องมี เป็นไปได้ที่จะทำตามขั้นตอนเหล่านั้นโดยอัตโนมัติ (ดูตัวอย่างคำตอบของ John) แต่พวกเขาต้องทำ ดังนั้นหากสิ่งที่คุณพยายามทำนั้นเหมือนกับ OP ไม่มีจริง ๆ ให้เป็นตัวอย่างและถ้าคุณกำลังพยายามทำสิ่งที่แตกต่างกันคุณควรถามคำถามใหม่ - นั่นคือ StackOverflow งาน! (และความคิดเห็นของคุณไม่ชัดเจน แต่การคาดเดาที่ดีที่สุดของฉันคือคุณต้องการสิ่งที่แตกต่างจาก OP ที่นี่ดังนั้นใช่คำถามใหม่)
Cascabel

ใช่ค่อนข้างแตกต่าง แต่คำตอบของคุณสมบูรณ์แบบสำหรับบริบท และฉันอาจไม่จำเป็นต้องถามอีกต่อไปเพียงเพราะคำตอบของคุณ Just: คำตอบที่ยอมรับนั้นใช้ git-up ซึ่งเป็นเพียงส่วนต่อประสานกับบรรทัดคำสั่ง git (ฉันถือว่า) ฉันหวังว่าคุณสามารถทำให้ชัดเจนในคำสั่ง git ไม่กี่บรรทัด คำตอบปัจจุบันไม่ได้คอมไพล์
mariotti

206

ฉันใช้คำsyncสั่งย่อยของฮับเพื่อทำสิ่งนี้โดยอัตโนมัติ ฉันมีalias git=hubในของฉัน.bash_profileดังนั้นคำสั่งที่ฉันพิมพ์คือ:

git sync

อัปเดตสาขาท้องถิ่นทั้งหมดที่มีสาขาอัปสตรีมที่ตรงกัน จากหน้าคน:

  • หากสาขาในประเทศล้าสมัยให้ส่งต่ออย่างรวดเร็ว
  • หากสาขาในพื้นที่มีงานที่ไม่ได้แจ้งเตือนให้เตือน
  • หากดูเหมือนว่าสาขาผสานและสาขาต้นน้ำของมันถูกลบให้ลบออก

นอกจากนี้ยังจัดการการ stashing / unstashing การเปลี่ยนแปลงแบบไม่มีข้อผูกมัดในสาขาปัจจุบัน

ฉันเคยใช้เครื่องมือที่คล้ายกันที่เรียกว่าgit-upแต่มันไม่ได้รับการบำรุงรักษาอีกต่อไปและgit syncทำสิ่งเดียวกันเกือบทั้งหมด


15
แล้ว Windows ล่ะ
Violet Giraffe

6
@ TrentonD.Adams ยอมรับวันที่และวันที่ผู้แต่งเป็นแนวคิดที่แตกต่าง การรีบูตจะเปลี่ยนวันที่ส่งมอบ แต่ไม่ใช่วันที่เขียน (ยกเว้นในกรณีที่มีข้อขัดแย้งที่วันที่ผู้เขียนเปลี่ยนแปลงด้วย) วันที่ของผู้เขียนสะท้อนเมื่อทรีคอมมิชชันถูกเขียนขึ้นและไม่ควรเปลี่ยนแปลงในช่วงรีบูตที่ไม่มีการโต้แย้ง วันที่ส่งมอบเปลี่ยนแปลงเนื่องจากการปฏิเสธจะสร้างการส่งมอบใหม่เสมอ ดังนั้นวันที่ส่งมอบจะอยู่ในลำดับที่ถูกต้องเสมอ
Dev

16
หากต้องการปิดพฤติกรรม rebasing git config --global git-up.rebase.auto falseอัตโนมัติของคอมไพล์ขึ้นวิ่ง
Dan Loewenherz

18
@MaxYankov การแชร์ประวัติการรีบูตเป็นสิ่งที่หลีกเลี่ยงได้ไม่มีอะไรผิดปกติในการรีบูตคอมมิชชันในช่วงดึง
Dev

23
การลดภาระคอมมิชชันคือการเขียนประวัติใหม่และทำให้ง่ายกว่าที่เป็นจริง ด้วยการรีบูตคุณอาจพบว่าตัวเองมีรหัสที่ผสานโดยอัตโนมัติ แต่ไม่ได้รวบรวมหรือแย่กว่านั้นคอมไพล์ แต่ไม่ทำงาน การผสานยอมรับวิธีการทำงานของคุณ: คุณได้ทำการเปลี่ยนแปลงและทดสอบก่อนที่จะรวมการเปลี่ยนแปลงของคนอื่นและการรวมการกระทำเป็นจุดที่มีประโยชน์มาก: นั่นคือสถานที่ที่คุณแน่ใจว่า chagesets ที่แตกต่างกันเล่นกันอย่างดี การรีบูตทำให้ดูเหมือนว่ากระบวนการนี้จะไม่เกิดขึ้นซึ่งไม่จริงและเป็นวิธีปฏิบัติที่อันตรายมาก
Max Yankov

39

ฉันรู้ว่าคำถามนี้เกือบ 3 ปีแล้ว แต่ฉันถามตัวเองด้วยคำถามเดียวกันและไม่พบวิธีแก้ปัญหาใด ๆ ดังนั้นฉันจึงสร้างคำสั่ง git เชลล์สคริปต์ของฉันเอง

ที่นี่มันจะไปgit-ffwd-updateสคริปต์ทำต่อไปนี้ ...

  1. มันออก a git remote updateเพื่อดึง revs lates
  2. จากนั้นใช้git remote showเพื่อรับรายการสาขาท้องถิ่นที่ติดตามสาขาระยะไกล (เช่นสาขาที่สามารถใช้ได้กับgit pull)
  3. จากนั้นจะตรวจสอบgit rev-list --count <REMOTE_BRANCH>..<LOCAL_BRANCH>ว่ามีสาขาที่สาขาอยู่เบื้องหลังรีโมท (และในทางกลับกัน)
  4. หากสาขาในพื้นที่เป็น 1 หรือมากกว่ามุ่งมั่นข้างหน้าก็สามารถ ไม่สามารถส่งต่อได้อย่างรวดเร็วและต้องมีการรวมหรือ rebased ด้วยมือ
  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-updatePATH

#!/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 ทำไมคุณไม่ใช้ git บน windows shell ธรรมดา? หากคุณใช้สิ่งที่ต้องการ cygwin สคริปต์นี้ก็ควรจะปรับการทำงาน ... ( แต่ผมยังไม่ได้ทดสอบ)
muhqu

@RyanWilcox ขอบคุณฉันใช้มันเหมือนทุก ๆ วัน (work-) ... ;-) คุณอาจต้องการดู dot-files ของฉันสำหรับสคริปต์และนามแฝงที่เกี่ยวข้องกับ git เพิ่มเติม: github.com/muhqu/dotfiles
muhqu

@muhqu ฉันพยายามที่จะใช้สคริปต์ของคุณและฉันไม่รู้ว่าทำไมมันถึงใช้งานได้เป็นครั้งแรก แต่มันไม่ทำงาน "อย่างที่คาด" ตอนนี้ ยกตัวอย่างให้ดูไปนี้ ทำไมมาสเตอร์ยังคงให้คำมั่นสัญญา 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
อาจเป็นการดีที่สุดที่จะไม่ใช้นามแฝงในสคริปต์ สิ่งนี้ยังไม่ได้ดึงข้อมูลจริงๆเพียงแค่ rebases ลงบนเนื้อหาที่ดึงมาแล้ว คุณควรเปลี่ยนgit rebase origin/$branchเป็นgit pullเพื่อให้สามารถดึงข้อมูลจากสาขาการติดตามที่เหมาะสม (น่าจะเป็นที่มา) และผสานหรือรีบูตตามที่กำหนดโดย config
Cascabel

@Jefromi: ฉันลืมไปfetchแล้ว มีการแก้ไข; คุณสมบัติพิเศษ / แก้ไขสิ่งที่ขึ้นอยู่กับ OP
Fred Foo

8
ฉันยังคิดว่าคุณอาจต้องการที่จะใช้pull(หรือตรวจสอบ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
นี่เป็นทางออกที่ฉันต้องการอย่างแน่นอน ฉันมักจะไม่ได้ทำการเปลี่ยนแปลง unpushed ในหลายสาขาและเพียงต้องการอัปเดตสาขาท้องถิ่นของฉันเพื่อให้ตรงกับรีโมต วิธีนี้ดีกว่าวิธีการลบ / ชำระเงินตามปกติของฉัน!
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

จาก manpage สำหรับ 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 คุณไม่สามารถทำได้ด้วยคำสั่งเดียว แต่คุณต้องทำc*nตามขั้นตอน (แทน 1) โดยที่cมีคำสั่งซ้ำจำนวนหนึ่งอยู่บ้างและnเป็นจำนวนสาขา
jww

@ jww ไม่ช่วย "หัวเราะที่ Git และ Fanboi" [sic] เมื่อเป็น VCS ที่คนส่วนใหญ่ใช้ในโลก แต่ฉันพูดนอกเรื่อง ... ฉันคิดว่าในบริบทของสคริปต์ "การดึงทั่วโลก" แบบนี้เป็นการระมัดระวังที่จะไม่พยายามเปลี่ยนแปลงสาขาที่ไม่หมุนเวียนหากพวกเขามีการรวมความขัดแย้งกัน
วิลล์

สิ่งนี้มีประโยชน์ขอขอบคุณ สิ่งเดียวที่ฉันไม่ชอบก็คือว่ามันสร้างสาขาในประเทศทุกสาขาที่ห่างไกล (รวมทั้งคนที่ฉันไม่สนใจ) ดังนั้นผมเปลี่ยน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

ปัญหานี้ยังไม่ได้รับการแก้ไข (อย่างน้อย) อย่างน้อยไม่ง่าย / ไม่มีสคริปต์: ดูโพสต์นี้ในรายชื่อผู้รับจดหมาย git โดย Junio ​​C Hamano อธิบายสถานการณ์และให้คำแนะนำง่ายๆ

เหตุผลสำคัญคือคุณไม่ควรต้องการสิ่งนี้:

ด้วยคอมไพล์ที่ไม่ใช่โบราณ (เช่น v1.5.0 หรือใหม่กว่า) ไม่มีเหตุผลที่จะมี "dev" ในท้องถิ่นที่ติดตามรีโมตอย่างแท้จริงอีกต่อไป หากคุณต้องการดูและดูเท่านั้นคุณสามารถตรวจสอบสาขาการติดตามระยะไกลได้โดยตรงที่ HEAD เดี่ยวด้วย " git checkout origin/dev"

ซึ่งหมายความว่ากรณีเดียวที่เราต้องทำให้สะดวกสำหรับผู้ใช้คือการจัดการสาขาในพื้นที่เหล่านี้ที่ "ติดตาม" รีโมตรีโมตเมื่อคุณมีการเปลี่ยนแปลงโลคัลหรือเมื่อคุณวางแผนที่จะมี

หากคุณมีการเปลี่ยนแปลงในท้องถิ่นของ "dev" ที่ถูกทำเครื่องหมายเพื่อติดตามการลบ "dev" และถ้าคุณอยู่ในสาขาที่แตกต่างจาก "dev" คุณไม่ควรทำอะไรหลังจากgit fetch"dev" อัปเดตการติดตามระยะไกล "dev" . มันจะไม่ไปข้างหน้าอย่างรวดเร็ว

การเรียกใช้โซลูชันมีไว้สำหรับตัวเลือกหรือสคริปต์ภายนอกเพื่อตัดสาขาท้องถิ่นที่ติดตามสาขาการติดตามระยะไกลในขณะนี้แทนที่จะทำการอัพเดทให้ทันสมัยโดยการส่งต่ออย่างรวดเร็วเช่นโปสเตอร์ต้นฉบับที่ร้องขอ

แล้วgit branch --prune --remote=<upstream>มันจะวนซ้ำไปตามกิ่งไม้ท้องถิ่นและถ้า

(1) ไม่ใช่สาขาปัจจุบัน และ
(2) มันถูกทำเครื่องหมายเพื่อติดตามสาขาที่นำมาจาก <upstream>; และ
(3) ไม่มีข้อผูกมัดใด ๆ

แล้วเอาสาขานั้นออก " git remote --prune-local-forks <upstream>" ก็ดีเช่นกัน ฉันไม่สนใจว่าคำสั่งใดจะใช้คุณลักษณะที่มีมาก

หมายเหตุ:ตั้งแต่ git 2.10 ไม่มีวิธีแก้ปัญหาดังกล่าว โปรดทราบว่าคำgit remote pruneสั่งย่อยและgit fetch --pruneกำลังจะลบสาขาการติดตามระยะไกลสำหรับสาขาที่ไม่มีอยู่ในระยะไกลอีกต่อไปไม่เกี่ยวกับการลบสาขาท้องถิ่นที่ติดตามสาขาการติดตามระยะไกล (ซึ่งสาขาการติดตามระยะไกลเป็นสาขาอัปสตรีม)


แทนที่จะโพสต์ลิงก์เท่านั้นโปรดโพสต์เนื้อหาจริงโดยใช้ลิงก์เป็นข้อมูลอ้างอิง ลิงค์นั้นตายไปแล้ว แย่มากฟังดูเหมือนสัญญา (ฉันรู้คำตอบนี้มาจากปี 2009 นี้จึงเป็นเพียงบันทึกสำหรับการอ้างอิงในอนาคต.)
ไมเคิล

ขอบคุณ (และว้าวตอบสนองอย่างรวดเร็วหลังจากหลายปี) ตอนนี้ฉันเห็นว่ากระทู้นี้เป็น " เรียกหาวิธีแก้ปัญหาง่ายๆ" ซึ่งตรงข้ามกับข้อผิดพลาดดั้งเดิมของฉัน " ให้คำตอบง่ายๆ"
ไมเคิล

@michael_n: ขยาย ... hmm ตอนนี้ฉันเห็นว่าโพสต์ไม่ได้เกี่ยวกับวิธีการแก้ปัญหาที่ร้องขอ แต่มันเกี่ยวกับปัญหา (สมมติว่าเป็นปัญหา 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

เพิ่มสคริปต์นี้ลง.profileใน Mac OS X:

# 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

นี่คือคำตอบที่ดี: วิธีดึงกิ่ง git ทั้งหมดได้อย่างไร

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

ทำไมคุณถึงแนะนำให้ทำgit fetchและgit pullแทนที่จะเป็นแค่git pull?
syntagma

ขอบคุณ ดูเหมือนว่าการดึงข้อมูลจะดึงสาขาทั้งหมดจากรีโมททั้งหมด เปลี่ยนแล้ว
milkovsky

8
สิ่งนี้จะดึงรีโมททั้งหมด แต่จะรวมเฉพาะสาขาปัจจุบัน หากคุณมี 10 รีโมตคุณจะต้องเช็กเอาต์แต่ละรายการด้วยตนเองแล้วผสาน
mpoisot

การทำเช่นนี้จะสร้างสาขาระยะไกลทั้งหมดในพื้นที่ด้วยorigin/คำนำหน้า
Yassine 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
    }

คุณสามารถให้ไฟล์ bat Windows ที่เทียบเท่าได้หรือไม่
Jaffy

1
@Jaffy ไม่แน่ใจว่าฉันมีเวลาเท่าไหร่ในมือของฉันและฉันไม่คล่องแคล่วในชุด แต่ฉันสามารถไปได้ ฉันจะโพสต์ความคืบหน้าของฉันที่นี่บางทีคนอื่นสามารถเข้ามาช่วยได้บ้าง
philosowaffle

3

หากคุณใช้ Windows คุณสามารถใช้PyGitUpซึ่งเป็นโคลนgit-upสำหรับ Python คุณสามารถติดตั้งโดยใช้pipด้วยpip install --user git-upหรือผ่านScoopโดยใช้scoop install git-up

[4]


3

เพียงโพสต์คำตอบที่อัปเดต git-upไม่ได้รับการบำรุงรักษาและหากคุณอ่านเอกสารที่พวกเขาพูดถึงการทำงานอยู่ในขณะนี้ที่มีอยู่ในคอมไพล์

ในฐานะของ Git 2.9 นั้น git pull --rebase - autoostash ทำสิ่งเดียวกัน

ดังนั้นหากคุณอัปเดตเป็น 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 ง่าย ๆ ก็เพียงพอแล้วด้วยการกำหนดค่าที่ถูกต้อง: stackoverflow.com/a/40067353/6309
VonC

โทรดีออกขอบคุณ @VonC ฉันปรับปรุงคำตอบของฉัน :) นอกจากนี้ยังอาจส่งประชาสัมพันธ์ไปยังgit-upเอกสารเพราะพวกเขาไม่พูดถึงว่า
สิงหาคม

git-upนี้ไม่ได้ปรับปรุงสาขาในประเทศทั้งหมดในครั้งเดียวซึ่งเป็นเหตุผลที่ผมส่วนใหญ่ใช้
เรย์

เอกสารการปรับปรุงล่าสุดเมื่อgit-up:)
สิงหาคม

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

ถ้าrefs / heads / masterสามารถส่งต่ออย่างรวดเร็วไปยังrefs / remotes / foo / masterผลลัพธ์ของ

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

ควรส่งคืนรหัส SHA1 ที่refs / heads / masterชี้ไปที่ ด้วยวิธีนี้คุณสามารถรวบรวมสคริปต์ที่จะอัปเดตสาขาท้องถิ่นทั้งหมดที่ไม่มีการโอนสายที่ใช้กับพวกเขาโดยอัตโนมัติ

เชลล์สคริปต์ตัวน้อยนี้ (ฉันเรียกมันว่า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

ฉันเองก็ไม่สามารถเขียนบทฮิลลูแนะนำและฉันก็ไม่มั่นใจพอที่จะใช้ความรู้คอมไพล์ของฉันเพื่อใช้ฐานข้อมูลคอมไพล์
นอร์แมนแรมซีย์

2
ฉันเกรงว่าฉันจะไม่เข้าใจโมเดลที่ดีพอที่จะใช้ประโยชน์จากสคริปต์ที่ได้รับมา มันเพียงพอแล้วที่จะทำให้คนคนหนึ่งอยากจะเปลี่ยนมาเป็น Mercurcial
นอร์แมนแรมซีย์

ฉันเองพบบทความของ 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เพื่อดูว่ากำลังทำอะไรอยู่

คำเตือน

สายการบินเดียวจะไม่ติดต่อรีโมทของคุณ ออก a git fetchหรือgit fetch --allก่อนเรียกใช้

สาขาเช็คเอาต์ในปัจจุบันจะไม่ได้รับการปรับปรุงด้วยข้อความเช่น

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

สำหรับสิ่งนี้คุณสามารถหันไปใช้วิธีปกติgit pull --ff-onlyได้

นามแฝง

เพิ่มสิ่งต่อไปนี้ในของคุณ.gitconfigเพื่อให้git fftดำเนินการคำสั่งนี้:

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

ดูของฉัน.gitconfigด้วย นามแฝงนั้นย่อมาจาก "การติดตามอย่างรวดเร็ว (สาขา)"


นี่คือวิธีการแก้ปัญหาที่ดี แต่ผมคิดว่าผมจะใช้Soluction propsed โดย @Johnสำหรับการส่งออกที่ดีขึ้นของมัน hub
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

นี่เป็นทางออกที่ดีและทำงานได้ดี ไม่มีใครสังเกตเห็นไหม?
วิลล์

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 line หนึ่งบรรทัด

หากต้องการอัปเดตสาขาทั้งหมดด้วยบรรทัดเดียวอย่างปลอดภัยนี่คือสิ่งที่ฉันทำ:

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นำเส้นด้วย a *และย้ายไปยังจุดสิ้นสุด (เพื่อให้สาขาปัจจุบันจะได้รับการปรับปรุงล่าสุด) จากนั้นก็เอา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. ไม่มีข้อผิดพลาดในการแยกวิเคราะห์ / แก้ไข regex

1
git fetch . refspecคุณสามารถหลีกเลี่ยงการตีเครือข่ายโดยใช้ .กล่าวสามารถดึงข้อมูลจากพื้นที่เก็บข้อมูลในปัจจุบันแทนจากรีโมทหนึ่งเดียว
hugomg

-1

ในฐานะของคอมไพล์ 2.9:

git pull --rebase --autostash

ดูhttps://git-scm.com/docs/git-rebase

สร้างที่เก็บชั่วคราวชั่วคราวโดยอัตโนมัติก่อนที่การดำเนินการจะเริ่มต้นและนำไปใช้หลังจากการดำเนินการสิ้นสุดลง ซึ่งหมายความว่าคุณสามารถเรียกใช้ rebase บน worktree ที่สกปรก อย่างไรก็ตามใช้ด้วยความระมัดระวัง: แอปพลิเคชันสะสมสุดท้ายหลังจากการรีบูตสำเร็จอาจทำให้เกิดข้อขัดแย้งที่ไม่สำคัญ


-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

ในสาขาหลักคุณสามารถอัปเดตสาขาอื่นทั้งหมด @Cascabel

ฉันไม่ทราบว่าเวอร์ชันใดแบ่ง / แก้ไขใน 2.17 (ซึ่งฉันใช้) มันสามารถทำงานได้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.