git pull
อาจเป็นการสร้างคอมมิต หากคุณทำการคอมมิตในเครื่องแล้วเรียกใช้git pull
หลังจากมีคนอื่นดันคอมมิตไปยังที่เก็บ Git จะดาวน์โหลดคอมมิตของนักพัฒนาคนอื่น ๆ แล้วรวมเข้ากับสาขาในพื้นที่ของคุณ
วิธีหลีกเลี่ยงการรวมการกระทำเหล่านี้ในอนาคต
คุณสามารถใช้git pull --rebase
เพื่อป้องกันไม่ให้เกิดขึ้นในอนาคต แต่ rebasing มีอันตรายของมันและผมขอแนะนำให้หลีกเลี่ยงการpull
ออกไปโดยสิ้นเชิง
แต่ขอแนะนำให้คุณทำตามรูปแบบการใช้งานนี้:
# download the latest commits
git remote update -p
# update the local branch
git merge --ff-only @{u}
# if the above fails with a complaint that the local branch has
# diverged:
git rebase -p @{u}
คำอธิบาย
git remote update -p
ดาวน์โหลดคอมมิตทั้งหมดในที่เก็บระยะไกลและอัพเดตสาขาการติดตามระยะไกล (เช่นorigin/master
) ไม่ได้สัมผัสกับไดเรกทอรีการทำงานดัชนีหรือสาขาในพื้นที่ของคุณ
-p
พรุนอาร์กิวเมนต์ลบสาขาต้นน้ำ ดังนั้นหากfoo
สาขาถูกลบในที่origin
เก็บgit remote update -p
จะลบการorigin/foo
อ้างอิงของคุณโดยอัตโนมัติ
git merge --ff-only @{u}
บอกให้ Git รวมสาขาต้นน้ำ ( @{u}
อาร์กิวเมนต์) เข้ากับสาขาในพื้นที่ของคุณ แต่เฉพาะในกรณีที่สาขาในพื้นที่ของคุณสามารถ "ส่งต่ออย่างรวดเร็ว" ไปยังสาขาต้นน้ำได้ (หรืออีกนัยหนึ่งก็คือหากไม่ได้แยกสาขา)
git rebase -p @{u}
ย้ายคอมมิตที่คุณทำไปได้อย่างมีประสิทธิภาพ แต่ยังไม่ได้ผลักดันไปที่ด้านบนของสาขาต้นน้ำซึ่งช่วยลดความจำเป็นในการสร้างการผสานที่โง่เขลาที่คุณพยายามหลีกเลี่ยง สิ่งนี้ช่วยปรับปรุงความเป็นเชิงเส้นของประวัติการพัฒนาทำให้ง่ายต่อการตรวจสอบ
-p
ตัวเลือกบอก Git เพื่อรักษาผสาน สิ่งนี้จะป้องกันไม่ให้ Git เป็นเส้นตรงของคอมมิตที่ถูก rebased master
นี้เป็นสิ่งสำคัญตัวอย่างเช่นถ้าคุณรวมสาขาคุณลักษณะลง โดยไม่ต้อง-p
ทุกกระทำในสาขาคุณลักษณะจะซ้ำกันในฐานะเป็นส่วนหนึ่งของการเชิงเส้นที่ทำโดยmaster
git rebase
สิ่งนี้จะทำให้การตรวจสอบประวัติการพัฒนายากขึ้นไม่ใช่เรื่องง่าย
ระวัง : git rebase
อาจไม่ทำในสิ่งที่คุณคาดหวังดังนั้นควรตรวจสอบผลลัพธ์ก่อนที่จะผลักดัน ตัวอย่างเช่น:
git log --graph --oneline --decorate --date-order --color --boundary @{u}..
ฉันชอบแนวทางนี้มากกว่าgit pull --rebase
ด้วยเหตุผลต่อไปนี้:
- ช่วยให้คุณเห็นการกระทำต้นน้ำที่เข้ามาก่อนที่คุณจะแก้ไขประวัติเพื่อรวมเข้าด้วยกัน
- ช่วยให้คุณสามารถส่งผ่านตัวเลือก
-p
( --preserve-merges
) ไปยังgit rebase
ในกรณีที่คุณต้องการสร้างฐานการผสานใหม่โดยเจตนา (เช่นการรวมสาขาคุณลักษณะที่ผลักไปแล้วเข้าไปmaster
)
ชวเลข: git up
แทนgit pull
เพื่อให้ง่ายต่อการดำเนินการข้างต้นฉันขอแนะนำให้สร้างนามแฝงที่เรียกว่าup
:
git config --global alias.up '!git remote update -p; git merge --ff-only @{u}'
ตอนนี้สิ่งที่คุณต้องทำเพื่อทำให้สาขาของคุณทันสมัยคือการเรียกใช้:
git up
git pull
แทน หากคุณได้รับข้อผิดพลาดเนื่องจากสาขาในพื้นที่ของคุณแตกต่างจากสาขาต้นน้ำนั่นคือจุดเริ่มต้นของคุณในการปรับฐาน
ทำไมไม่git pull --rebase
?
ทำงานgit pull --rebase
เทียบเท่ากับการทำงานตามgit fetch
git rebase
การดำเนินการนี้จะพยายามกรอไปข้างหน้าไปยังการคอมมิตต้นน้ำใหม่ แต่ถ้าทำไม่ได้มันจะสร้างฐานการคอมมิชชันในเครื่องของคุณใหม่ในการคอมมิตต้นน้ำใหม่ โดยปกติจะใช้ได้ แต่ระวัง:
- Rebase เป็นหัวข้อขั้นสูงและคุณควรเข้าใจผลกระทบก่อนที่จะทำการรีเบส
git pull --rebase
ไม่เปิดโอกาสให้คุณตรวจสอบการกระทำก่อนที่จะรวมเข้าด้วยกัน ทั้งนี้ขึ้นอยู่กับว่ามีอะไรเปลี่ยนแปลงต้นน้ำก็เป็นไปได้มากที่ rebase คือการดำเนินงานผิดrebase --onto
, merge
, reset
หรืออาจจะเหมาะสมกว่าธรรมดาpush -f
rebase
- (ในปัจจุบัน) ไม่สามารถส่งผ่าน
--preserve-merges
ไปยังการดำเนินการ rebase ได้ดังนั้นการรวมสาขาคุณลักษณะโดยเจตนาใด ๆ จะถูกทำให้เป็นเชิงเส้นการเล่นซ้ำ (และการทำซ้ำ) ทั้งหมดของสาขาคุณลักษณะจะกระทำ
"แก้ไข" คอมมิตการผสานที่มีอยู่ที่สร้างขึ้นโดย git pull
หากคุณยังไม่ได้พุชการรวมคอมมิตที่สร้างโดยgit pull
คุณสามารถกำหนดฐานข้อมูลการผสานใหม่ได้ สมมติว่าคุณไม่ได้ทำการผสานโดยเจตนาใด ๆ (เช่นการรวมสาขาฟีเจอร์ที่ผลักไปแล้วเข้ากับสาขาปัจจุบันของคุณ) สิ่งต่อไปนี้ควรทำ:
git rebase @{u}
คำสั่งด้านบนบอกให้ Git เลือกคอมHEAD
มิตที่ไม่ผสานทั้งหมดที่เข้าถึงได้จาก(คอมมิตปัจจุบัน) ลบคอมมิตทั้งหมดที่เข้าถึงได้@{u}
(ซึ่งเป็นชวเลขสำหรับ "สาขาต้นน้ำ" คือorigin/master
ถ้าHEAD
เป็นmaster
) เล่นซ้ำ (เชอร์รี่ - รับ ) ไว้ที่ด้านบนของสาขาต้นน้ำจากนั้นย้ายการอ้างอิงสาขาปัจจุบันเพื่อชี้ไปที่ผลลัพธ์ของการเล่นคอมมิตซ้ำ git pull
ได้อย่างมีประสิทธิภาพย้ายกระทำที่ไม่ตัดเข้าสู่ต้นน้ำล่าสุดกระทำซึ่งช่วยขจัดผสานที่สร้างขึ้นโดย
หากคุณมีการรวมคอมมิตโดยเจตนาคุณไม่ต้องการเรียกใช้git rebase @{u}
เพราะจะเล่นซ้ำทุกอย่างจากอีกสาขา การจัดการกับกรณีนี้มีความซับซ้อนมากขึ้นซึ่งเป็นเหตุผลว่าทำไมจึงควรใช้git up
และหลีกเลี่ยงgit pull
โดยสิ้นเชิง คุณอาจจะต้องใช้reset
ในการยกเลิกการผสานสร้างขึ้นโดยแล้วทำpull
อาร์กิวเมนต์ไม่ได้ทำงานได้อย่างน่าเชื่อถือสำหรับฉันดังนั้นคุณอาจท้ายต้องใช้เพื่อยกเลิกการผสานเจตนาปรับปรุงสาขาท้องถิ่นของคุณและจากนั้นทำซ้ำผสานเจตนา (ซึ่งเป็นความเจ็บปวดถ้ามีจำนวนมากของการผสานขน ความขัดแย้ง)git rebase -p @{u}
-p
git rebase
reset
@{u}