ผสานอัปเดตและดึงกิ่ง Git โดยไม่ต้องใช้การชำระเงิน


628

ฉันทำงานในโครงการที่มี 2 สาขาคือ A และ B โดยปกติฉันทำงานในสาขา A และรวมสิ่งต่าง ๆ จากสาขา B สำหรับการรวมฉันมักจะทำ:

git merge origin/branchB

อย่างไรก็ตามฉันต้องการเก็บสำเนา B สาขาในท้องที่ด้วยเนื่องจากฉันอาจตรวจสอบสาขาเป็นครั้งคราวโดยไม่รวมกับสาขา A ของฉันก่อนสำหรับสิ่งนี้ฉันจะทำ:

git checkout branchB
git pull
git checkout branchA

มีวิธีการข้างต้นในคำสั่งเดียวและโดยไม่ต้องสลับสาขาไปมา? ฉันควรจะใช้git update-refเพื่อสิ่งนั้นหรือไม่? อย่างไร?



1
คำตอบของยาคุบต่อคำถามแรกที่เชื่อมโยงอธิบายว่าทำไมสิ่งนี้จึงเป็นไปไม่ได้โดยทั่วไป คำอธิบาย (ด้านหลัง) อีกข้อหนึ่งคือคุณไม่สามารถผสานใน repo ที่เปลือยเปล่าได้ดังนั้นจึงต้องมีแผนผังการทำงาน
Cascabel

3
@Eric: สาเหตุที่พบบ่อยคือการชำระเงินใช้เวลานานสำหรับ repos ขนาดใหญ่และพวกเขาอัปเดต timestamps แม้ว่าคุณจะกลับไปเป็นเวอร์ชั่นเดียวกันดังนั้นคิดว่าทุกอย่างต้องสร้างใหม่
Cascabel

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

ดูยังผสานโดยไม่ต้องเปลี่ยนไดเรกทอรีการทำงาน

คำตอบ:


972

คำตอบสั้น ๆ

ตราบใดที่คุณทำการผสานอย่างรวดเร็วจากนั้นคุณก็สามารถใช้

git fetch <remote> <sourceBranch>:<destinationBranch>

ตัวอย่าง:

# Merge local branch foo into local branch master,
# without having to checkout master first.
# Here `.` means to use the local repository as the "remote":
git fetch . foo:master

# Merge remote branch origin/foo into local branch foo,
# without having to checkout foo first:
git fetch origin foo:foo

ในขณะที่คำตอบของแอมเบอร์จะทำงานในกรณีที่ส่งต่ออย่างรวดเร็วด้วยการใช้git fetchวิธีนี้แทนที่จะปลอดภัยกว่าการบังคับให้ย้ายการอ้างอิงสาขาเพียงเล็กน้อยเนื่องจากgit fetchจะป้องกันการไม่ส่งต่อโดยไม่ตั้งใจโดยอัตโนมัติตราบใดที่คุณไม่ได้ใช้งานโดยอัตโนมัติ+ใน refspec

คำตอบยาว ๆ

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

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

นี่คือตัวอย่างของการอัปเดตmaster(ไม่อนุญาตการเปลี่ยนแปลงที่ไม่ใช่การกรอไปข้างหน้า) หากคุณมีสาขาอื่นfeatureเช็คเอาต์:

git fetch upstream master:master

กรณีการใช้งานนี้เป็นเรื่องธรรมดามากที่คุณอาจต้องการสร้างนามแฝงในไฟล์กำหนดค่า git ของคุณเช่นนี้

[alias]
    sync = !sh -c 'git checkout --quiet HEAD; git fetch upstream master:master; git checkout --quiet -'

นามแฝงนี้ทำอะไรได้บ้างดังต่อไปนี้:

  1. git checkout HEAD: สิ่งนี้ทำให้สำเนาการทำงานของคุณเข้าสู่สถานะแยกหัว สิ่งนี้มีประโยชน์หากคุณต้องการอัปเดตmasterในขณะที่คุณเช็คเอาต์ ฉันคิดว่ามันจำเป็นที่จะต้องทำด้วยเพราะไม่เช่นนั้นการอ้างอิงสาขาmasterจะไม่ย้าย แต่ฉันจำไม่ได้ว่าเป็นสิ่งที่ถูกต้องหรือไม่

  2. git fetch upstream master:master: สิ่งนี้จะส่งต่อไปmasterยังท้องถิ่นของคุณไปยังสถานที่เดียวกันอย่างupstream/masterรวดเร็ว

  3. git checkout -ตรวจสอบสาขาที่เช็คเอาท์ก่อนหน้าของคุณ (เป็นสิ่งที่-ทำในกรณีนี้)

ไวยากรณ์ของgit fetchการผสานอย่างรวดเร็ว (ไม่ใช่ -)

หากคุณต้องการให้fetchคำสั่งล้มเหลวหากการอัปเดตไม่ใช่การส่งต่ออย่างรวดเร็วคุณเพียงแค่ใช้ refspec ของแบบฟอร์ม

git fetch <remote> <remoteBranch>:<localBranch>

หากคุณต้องการอนุญาตการอัปเดตที่ไม่ใช่การส่งต่อคุณต้องเพิ่ม a +ที่ด้านหน้าของ refspec:

git fetch <remote> +<remoteBranch>:<localBranch>

โปรดทราบว่าคุณสามารถส่งผ่าน repo ท้องถิ่นของคุณเป็นพารามิเตอร์ "ระยะไกล" โดยใช้.:

git fetch . <sourceBranch>:<destinationBranch>

เอกสารประกอบ

จากgit fetchเอกสารที่อธิบายเกี่ยวกับไวยากรณ์นี้ (การเน้นของฉัน):

<refspec>

รูปแบบของ<refspec>พารามิเตอร์เป็นบวกตัวเลือก+ตามด้วยเตะแหล่งที่มา<src>, ตามด้วยเครื่องหมายตามด้วยเตะปลายทาง:<dst>

ได้รับเตะแมตช์ระยะไกลที่<src>เป็นความจริงและถ้า<dst>ไม่ได้เป็นสตริงที่ว่างเปล่า, <src>ได้รับเตะท้องถิ่นที่ตรงกับมันเป็นอย่างรวดเร็วส่งต่อโดยใช้ หากใช้เครื่องหมายบวก+เป็นทางเลือกการอ้างอิงในท้องถิ่นจะได้รับการอัปเดตแม้ว่าจะไม่ส่งผลให้มีการอัปเดตอย่างรวดเร็ว

ดูสิ่งนี้ด้วย

  1. ชำระเงิน Git และผสานโดยไม่ต้องสัมผัสต้นไม้ทำงาน

  2. ผสานโดยไม่ต้องเปลี่ยนไดเรกทอรีทำงาน


3
git checkout --quiet HEADคือgit checkout --quiet --detachเป็นของ Git 1.7.5
Rafa

6
ฉันพบว่าฉันต้องทำ: git fetch . origin/foo:fooเพื่ออัปเดต foo ในพื้นที่ของฉันเป็นที่มา / foo ในพื้นที่ของฉัน
weston

3
มีเหตุผล "การชำระเงิน git HEAD --quiet" และ "git checkout --quiet -" รวมอยู่ในคำตอบที่ยาว แต่ไม่ใช่คำตอบสั้น ๆ ใช่ไหม ฉันเดาว่าเป็นเพราะสคริปต์อาจทำงานได้เมื่อคุณชำระเงินแล้วแม้ว่าคุณจะทำ git pull ได้หรือไม่
ฌอน

8
เหตุใดจึง 'เรียก' คำสั่งให้ทำ 'ผสาน' ที่นี่ ... มันไม่สมเหตุสมผลเลย หาก 'ดึง' คือ 'ดึงข้อมูล' แล้วตามด้วย 'ผสาน' จะต้องมี 'ตรรกะ' - เท่านั้นที่เทียบเท่าซึ่งจะอัปเดต 'สาขา' จาก 'ต้นกำเนิด / สาขา' ในเครื่องเนื่องจาก 'ดึง' มี ถูกเรียกใช้แล้ว
เอ็ด Randall

1
ขอบคุณสำหรับgit checkout -เคล็ดลับ! cd -เพียงแค่เป็นเรื่องง่ายเหมือน
ม้า

84

ไม่ไม่มี การชำระเงินของสาขาเป้าหมายจำเป็นเพื่อให้คุณสามารถแก้ไขข้อขัดแย้งเหนือสิ่งอื่นใด (หาก Git ไม่สามารถผสานได้โดยอัตโนมัติ)

อย่างไรก็ตามหากการผสานเป็นสิ่งที่จะต้องกรอไปข้างหน้าคุณไม่จำเป็นต้องตรวจสอบสาขาเป้าหมายเพราะคุณไม่จำเป็นต้องผสานอะไรเลย - สิ่งที่คุณต้องทำคืออัพเดทสาขาให้ชี้ไปที่ อ้างอิงหัวใหม่ คุณสามารถทำได้ด้วยgit branch -f:

git branch -f branch-b branch-a

จะอัปเดตbranch-bให้ชี้ไปที่ส่วนหัวของbranch-aไปยังจุดที่หัวของ

-fตัวเลือกที่ย่อมา--forceซึ่งหมายความว่าคุณจะต้องระมัดระวังเมื่อใช้มัน

อย่าใช้มันหากคุณไม่แน่ใจว่าการผสานจะเป็นไปอย่างรวดเร็ว


46
เพียงระวังอย่าทำอย่างนั้นถ้าคุณไม่แน่ใจว่าการผสานจะเป็นไปอย่างรวดเร็ว! ไม่ต้องการที่จะตระหนักในภายหลังคุณได้วางผิดสัญญา
Cascabel

@FuadSaud ไม่ถูกต้อง git resetใช้งานได้เฉพาะสาขาที่เช็คเอาท์ในปัจจุบัน
เหลืองอำพัน

9
ผลลัพธ์เดียวกัน (การส่งต่ออย่างรวดเร็ว) ทำได้โดยgit fetch upstream branch-b:branch-b(นำมาจากคำตอบนี้ )
Oliver

6
หากต้องการขยายความคิดเห็นของ @ Oliver คุณสามารถทำได้git fetch <remote> B:Aโดยที่ B และ A เป็นสาขาที่แตกต่างกันโดยสิ้นเชิง แต่ B สามารถผสานการส่งต่ออย่างรวดเร็วไปยัง A. ได้คุณยังสามารถส่งผ่านที่เก็บในเครื่องของคุณเป็น "remote" โดยใช้.เป็นนามแฝงระยะไกลgit fetch . B:A.

8
คำถามของ OP ทำให้ชัดเจนว่าการรวมจะเป็นไปอย่างรวดเร็ว โดยไม่คำนึงถึงbranch -fอาจเป็นอันตรายตามที่คุณชี้ให้เห็น ดังนั้นอย่าใช้มัน! ใช้fetch origin branchB:branchBซึ่งจะล้มเหลวอย่างปลอดภัยหากการผสานไม่ได้ส่งต่ออย่างรวดเร็ว
Bennett McElwee

30

แอมเบอร์กล่าวว่าการรวมกันอย่างรวดเร็วเป็นกรณีเดียวที่คุณอาจทำเช่นนี้ได้ การผสานอื่นใดที่เป็นไปได้ต้องผ่านการผสานสามทางทั้งการใช้แพทช์การแก้ไขข้อตกลงความขัดแย้ง - และนั่นหมายความว่าจำเป็นต้องมีไฟล์อยู่รอบ ๆ

ฉันบังเอิญมีสคริปต์อยู่รอบตัวฉันสำหรับสิ่งนี้: ทำการผสานอย่างรวดเร็วโดยไม่ต้องแตะที่แผนผังการทำงาน (เว้นแต่คุณจะรวมเข้ากับ HEAD) มันยาวไปหน่อยเพราะอย่างน้อยก็มีความทนทาน - มันตรวจสอบเพื่อให้แน่ใจว่าการผสานนั้นจะเป็นไปข้างหน้าอย่างรวดเร็วจากนั้นทำการดำเนินการโดยไม่ต้องตรวจสอบสาขา แต่ให้ผลลัพธ์เหมือนคุณได้เห็นdiff --statสรุปการเปลี่ยนแปลงและรายการใน reflog เป็นเหมือนกับการผสานไปข้างหน้าอย่างรวดเร็วแทนการ "ตั้งค่า" branch -fหนึ่งคุณจะได้รับถ้าคุณใช้ ถ้าคุณชื่อมันและวางไว้ในไดเรกทอรีถังของคุณคุณสามารถเรียกว่าเป็นคำสั่งคอมไพล์:git-merge-ffgit merge-ff

#!/bin/bash

_usage() {
    echo "Usage: git merge-ff <branch> <committish-to-merge>" 1>&2
    exit 1
}

_merge_ff() {
    branch="$1"
    commit="$2"

    branch_orig_hash="$(git show-ref -s --verify refs/heads/$branch 2> /dev/null)"
    if [ $? -ne 0 ]; then
        echo "Error: unknown branch $branch" 1>&2
        _usage
    fi

    commit_orig_hash="$(git rev-parse --verify $commit 2> /dev/null)"
    if [ $? -ne 0 ]; then
        echo "Error: unknown revision $commit" 1>&2
        _usage
    fi

    if [ "$(git symbolic-ref HEAD)" = "refs/heads/$branch" ]; then
        git merge $quiet --ff-only "$commit"
    else
        if [ "$(git merge-base $branch_orig_hash $commit_orig_hash)" != "$branch_orig_hash" ]; then
            echo "Error: merging $commit into $branch would not be a fast-forward" 1>&2
            exit 1
        fi
        echo "Updating ${branch_orig_hash:0:7}..${commit_orig_hash:0:7}"
        if git update-ref -m "merge $commit: Fast forward" "refs/heads/$branch" "$commit_orig_hash" "$branch_orig_hash"; then
            if [ -z $quiet ]; then
                echo "Fast forward"
                git diff --stat "$branch@{1}" "$branch"
            fi
        else
            echo "Error: fast forward using update-ref failed" 1>&2
        fi
    fi
}

while getopts "q" opt; do
    case $opt in
        q ) quiet="-q";;
        * ) ;;
    esac
done
shift $((OPTIND-1))

case $# in
    2 ) _merge_ff "$1" "$2";;
    * ) _usage
esac

ป.ล. หากใครเห็นปัญหาเกี่ยวกับสคริปต์นี้โปรดแสดงความคิดเห็น! มันเป็นเขียนและลืมงาน แต่ฉันมีความสุขที่จะปรับปรุงมัน


คุณอาจสนใจในstackoverflow.com/a/5148202/717355เพื่อการเปรียบเทียบ
Philip Oakley

@PhilipOakley จากการมองอย่างรวดเร็วว่าที่หลักทำสิ่งเดียวกันกับของฉัน แต่ฉันไม่ได้ฮาร์ดโค้ดเพียงกิ่งเดียวมันมีข้อผิดพลาดมากขึ้นมันจำลองเอาท์พุทของ git-merge และมันทำในสิ่งที่คุณหมายถึงถ้าคุณเรียกมันในขณะที่คุณอยู่บนกิ่งไม้จริง ๆ
Cascabel

ฉันมีของคุณอยู่ในไดเรกทอรี \ bin ของฉัน ;-) ฉันเพิ่งลืมมันไปและมองไปรอบ ๆ เห็นสคริปต์นั้นและทำให้ฉันจำได้! สำเนาของฉันมีลิงก์นี้และ# or git branch -f localbranch remote/remotebranchเพื่อเตือนฉันถึงแหล่งที่มาและตัวเลือกต่างๆ แสดงความคิดเห็นของคุณในลิงค์อื่น ๆ +1
Philip Oakley

3
+1 ยังสามารถกำหนด"$branch@{u}"เป็นคอมมิชชันเพื่อรวมเพื่อรับ
อั

ขอบคุณ! โอกาสใดที่คุณสามารถใช้ตัวอย่างง่ายๆในการตอบได้?
nmr

20

คุณสามารถทำได้หากการผสานเป็นการส่งต่อที่รวดเร็ว หากไม่เป็นเช่นนั้น git จะต้องทำการตรวจสอบไฟล์เพื่อให้สามารถรวมมันได้!

หากต้องการทำเพื่อการกรอไปข้างหน้าเท่านั้น :

git fetch <branch that would be pulled for branchB>
git update-ref -m "merge <commit>: Fast forward" refs/heads/<branch> <commit>

ที่<commit>เป็นความจริงกระทำการอย่างใดอย่างหนึ่งที่คุณต้องการได้อย่างรวดเร็วไปข้างหน้าเพื่อ นี่คือการใช้โดยทั่วไปgit branch -fจะเพื่อย้ายสาขายกเว้นว่าจะบันทึกใน reflog เหมือนว่าคุณได้ทำการผสาน

ได้โปรดได้โปรดอย่าทำสิ่งนี้เพื่อสิ่งที่ไม่ใช่การก้าวไปข้างหน้าไม่อย่างนั้นคุณจะทำการรีเซ็ตสาขาของคุณให้เป็นหน้าที่อื่น (ในการตรวจสอบดูว่าgit merge-base <branch> <commit>ให้ SHA1 ของสาขาหรือไม่)


4
มีวิธีที่จะทำให้มันล้มเหลวหรือไม่หากไม่สามารถเดินหน้าอย่างรวดเร็ว?
gman

2
@gman git merge-base --is-ancestor <A> <B>คุณสามารถใช้ "B" เป็นสิ่งที่ต้องรวมเข้ากับ "A" ตัวอย่างจะเป็น A = master และ B = พัฒนาเพื่อให้แน่ใจว่าการพัฒนานั้นสามารถส่งต่อได้อย่างรวดเร็วเป็น Master หมายเหตุ: มันมีอยู่ด้วย 0 ถ้ามันไม่สามารถ ff, มีอยู่ด้วย 1 ถ้ามันเป็น
eddiemoya

1
ไม่ได้บันทึกไว้ใน git-scm แต่อยู่ใน kernal.org kernel.org/pub/software/scm/git/docs/git-merge-base.html
eddiemoya

ทำสรุปสั้น ๆ เพื่อสรุปสิ่งที่ฉันพูดถึง (ไม่ได้ทดสอบจริง ๆ แต่ควรพาคุณไปที่นั่นเป็นส่วนใหญ่) gist.github.com/eddiemoya/ad4285b2d8a6bdabf432 ---- เป็น side side ฉันมีประโยชน์มากที่สุดฉันมีสคริปต์ที่ตรวจสอบ ff และถ้าไม่ให้คุณรีบูทสาขาที่ต้องการก่อน - จากนั้น ff ผสาน - ทั้งหมดโดยไม่ต้องตรวจสอบอะไรออก
eddiemoya

12

ในกรณีของคุณคุณสามารถใช้

git fetch origin branchB:branchB

ซึ่งทำในสิ่งที่คุณต้องการ (สมมติว่าการผสานนั้นเป็นกรอไปข้างหน้า) หากไม่สามารถอัปเดตสาขาได้เนื่องจากต้องการการผสานที่ไม่ใช่กรอเดินหน้าจะทำให้ข้อความล้มเหลวอย่างปลอดภัย

การดึงข้อมูลรูปแบบนี้มีตัวเลือกที่มีประโยชน์มากกว่านี้ด้วยเช่นกัน:

git fetch <remote> <sourceBranch>:<destinationBranch>

โปรดทราบว่า<remote> สามารถเป็นพื้นที่เก็บข้อมูลในท้องถิ่นและ<sourceBranch>สามารถเป็นสาขาการติดตาม ดังนั้นคุณสามารถอัปเดตสาขาในท้องที่แม้ว่าจะไม่ได้ชำระเงินโดยไม่ต้องเข้าถึงเครือข่ายได้โดยไม่ต้องเข้าถึงเครือข่าย

ขณะนี้การเข้าถึงเซิร์ฟเวอร์ upstream ของฉันผ่าน VPN ที่ช้าดังนั้นฉันจึงเชื่อมต่อเป็นระยะgit fetchเพื่ออัปเดตรีโมททั้งหมดแล้วตัดการเชื่อมต่อ จากนั้นถ้าพูดว่าเจ้านายระยะไกลมีการเปลี่ยนแปลงฉันสามารถทำได้

git fetch . remotes/origin/master:master

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


11

วิธีอื่นที่เป็นที่ยอมรับกันโดยทั่วไปคือการสร้างสาขาขึ้นใหม่:

git fetch remote
git branch -f localbranch remote/remotebranch

สิ่งนี้จะละทิ้งสาขาที่ล้าสมัยในท้องถิ่นและสร้างใหม่อีกครั้งด้วยชื่อเดียวกันดังนั้นใช้ด้วยความระมัดระวัง ...


ฉันเพิ่งเห็นว่าคำตอบเดิมกล่าวถึงสาขาแล้ว -f ... ถึงกระนั้นฉันยังไม่เห็นข้อได้เปรียบในการรวมการอ้างอิงในกรณีการใช้งานที่อธิบายไว้ในตอนแรก
kkoehne

7

คุณสามารถโคลน repo และทำการรวมใน repo ใหม่ ในระบบไฟล์เดียวกันสิ่งนี้จะฮาร์ดลิงก์แทนที่จะคัดลอกข้อมูลส่วนใหญ่ เสร็จสิ้นโดยดึงผลลัพธ์ลงใน repo ดั้งเดิม


4

ป้อนgit-forward-merge :

โดยไม่จำเป็นต้องเช็คเอาต์ปลายทางgit-forward-merge <source> <destination>รวมแหล่งข้อมูลเข้ากับสาขาปลายทาง

https://github.com/schuyler1d/git-forward-merge

ใช้งานได้สำหรับการผสานอัตโนมัติเท่านั้นหากมีข้อขัดแย้งที่คุณต้องใช้ในการผสานปกติ


2
ฉันคิดว่าสิ่งนี้ดีกว่าการเรียก git <remote> <source>: <destination> เพราะการกรอไปข้างหน้าเป็นการดำเนินการของการผสานที่ไม่ดึงข้อมูลและง่ายต่อการเขียน สิ่งที่ไม่ดีแม้ว่ามันไม่ได้อยู่ในคอมไพล์เริ่มต้น
Binarian

4

สำหรับหลายกรณี (เช่นการรวม) คุณสามารถใช้สาขาระยะไกลได้โดยไม่ต้องอัปเดตสาขาการติดตามโลคัล การเพิ่มข้อความใน reflog เสียงเหมือน overkill และจะหยุดมันเร็วกว่า เพื่อให้ง่ายต่อการกู้คืนเพิ่มสิ่งต่อไปนี้ในการกำหนดค่า git ของคุณ

[core]
    logallrefupdates=true

จากนั้นพิมพ์

git reflog show mybranch

เพื่อดูประวัติล่าสุดสำหรับสาขาของคุณ


ฉันคิดว่าส่วนจะต้อง[core]ไม่[user]? (และเป็นค่าเริ่มต้นในสำหรับ repos ที่มีพื้นที่ทำงาน (เช่นไม่เปลือย)
eckes

3

ฉันเขียนฟังก์ชันเชลล์สำหรับกรณีการใช้งานที่คล้ายกันซึ่งฉันพบทุกวันในโครงการ นี่เป็นทางลัดในการทำให้สาขาท้องถิ่นทันสมัยด้วยสาขาทั่วไปเช่นการพัฒนาก่อนที่จะเปิดการประชาสัมพันธ์ ฯลฯ

การโพสต์สิ่งนี้แม้ว่าคุณไม่ต้องการใช้checkoutในกรณีที่คนอื่นไม่สนใจข้อ จำกัด นั้น

glmh( "ดึงคอมไพล์และผสานนี่") โดยอัตโนมัติจะcheckout branchB, pullล่าสุดอีกครั้งcheckout branchAและmerge branchBและ

ไม่ตอบสนองความต้องการในการเก็บสำเนา BranchA ในเครื่อง แต่สามารถแก้ไขได้ง่าย ๆ โดยเพิ่มขั้นตอนก่อนเช็คเอาท์ BranchB สิ่งที่ต้องการ...

git branch ${branchA}-no-branchB ${branchA}

สำหรับการผสานการกรอไปข้างหน้าอย่างง่ายนี้จะข้ามไปยังข้อความแจ้งเตือนการกระทำ

สำหรับการรวมที่ไม่ใช่การส่งต่ออย่างรวดเร็วสาขาของคุณจะอยู่ในสถานะการแก้ไขข้อขัดแย้ง (คุณอาจต้องเข้าไปแทรกแซง)

หากต้องการตั้งค่าเพิ่ม.bashrcหรือ.zshrcฯลฯ :

glmh() {
    branchB=$1
    [ $# -eq 0 ] && { branchB="develop" }
    branchA="$(git branch | grep '*' | sed 's/* //g')"
    git checkout ${branchB} && git pull
    git checkout ${branchA} && git merge ${branchB} 
}

การใช้งาน:

# No argument given, will assume "develop"
> glmh

# Pass an argument to pull and merge a specific branch
> glmh your-other-branch

หมายเหตุ: สิ่งนี้ไม่แข็งแรงพอที่จะส่งมอบ args นอกเหนือจากชื่อสาขาไปgit merge


2

อีกวิธีในการทำสิ่งนี้อย่างมีประสิทธิภาพคือ:

git fetch
git branch -d branchB
git branch -t branchB origin/branchB

เนื่องจากเป็นตัวพิมพ์เล็ก-dจึงจะลบได้ก็ต่อเมื่อข้อมูลยังคงอยู่ที่ใดที่หนึ่ง มันคล้ายกับคำตอบของ @ kkoehne ยกเว้นว่าไม่ได้บังคับ เนื่องจากว่า-tว่ามันจะทำการตั้งค่ารีโมตอีกครั้ง

ฉันมีความต้องการแตกต่างจาก OP เล็กน้อยซึ่งก็คือการสร้างฟีเจอร์ใหม่ที่จะปิดสาขาdevelop(หรือmaster) หลังจากรวมคำขอดึงเข้า ที่สามารถทำได้ในหนึ่งซับโดยไม่ต้องบังคับ แต่มันไม่ได้ปรับปรุงdevelopสาขาในท้องถิ่น เป็นเพียงเรื่องของการตรวจสอบสาขาใหม่และให้เป็นไปตามorigin/develop:

git checkout -b new-feature origin/develop

1

เพียงแค่ดึงต้นแบบโดยไม่ต้องตรวจสอบต้นแบบที่ฉันใช้

git fetch origin master:master


1

มันเป็นไปได้อย่างยิ่งที่จะทำผสานใด ๆ git checkoutแม้จะไม่ใช่อย่างรวดเร็วผสานไปข้างหน้าโดยไม่ต้อง worktreeคำตอบโดย @grego เป็นคำแนะนำที่ดี หากต้องการขยาย:

cd local_repo
git worktree add _master_wt master
cd _master_wt
git pull origin master:master
git merge --no-ff -m "merging workbranch" my_work_branch
cd ..
git worktree remove _master_wt

ตอนนี้คุณได้รวมสาขางานในท้องถิ่นเป็นmasterสาขาท้องถิ่นโดยไม่ต้องเปลี่ยนเช็คเอาต์


1

หากคุณต้องการให้ต้นไม้เดียวกันกับสาขาใดสาขาหนึ่งที่คุณต้องการผสาน (เช่นไม่ใช่ "การรวม" จริง) คุณสามารถทำเช่นนี้ได้

# Check if you can fast-forward
if git merge-base --is-ancestor a b; then
    git update-ref refs/heads/a refs/heads/b
    exit
fi

# Else, create a "merge" commit
commit="$(git commit-tree -p a -p b -m "merge b into a" "$(git show -s --pretty=format:%T b)")"
# And update the branch to point to that commit
git update-ref refs/heads/a "$commit"

1
git worktree add [-f] [--detach] [--checkout] [--lock] [-b <new-branch>] <path> [<commit-ish>]

คุณสามารถลอง git worktreeเปิดสาขาสองข้างได้เสียงนี้อาจเป็นสิ่งที่คุณต้องการ แต่แตกต่างจากคำตอบอื่น ๆ ที่ฉันเคยเห็นที่นี่

ด้วยวิธีนี้คุณสามารถมีสองสาขาแยกกันติดตามใน repo git เดียวกันดังนั้นคุณต้องดึงเพียงครั้งเดียวเพื่อรับการอัพเดตในต้นไม้ทำงานทั้งสอง (แทนที่จะต้องคอมไพล์โคลนสองครั้งและดึง git แต่ละครั้ง)

Worktree จะสร้างไดเรกทอรีการทำงานใหม่สำหรับรหัสของคุณซึ่งคุณสามารถมีสาขาที่แตกต่างกันตรวจสอบพร้อมกันแทนการแลกเปลี่ยนสาขาในสถานที่

เมื่อคุณต้องการลบคุณสามารถทำความสะอาดด้วย

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