วิธีผสานไฟล์ที่ต้องการจากกิ่ง Git


179

ฉันมี 2 git branch branch1 และ branch2 และฉันต้องการรวม file.py ใน branch2 เข้ากับ file.py ใน branch1 และเฉพาะไฟล์นั้น

ในสาระสำคัญฉันต้องการทำงานกับ file.py ใน branch1 แต่ต้องการใช้ประโยชน์จากคำสั่ง merge วิธีที่ดีที่สุดในการทำเช่นนี้คืออะไร?



คำตอบ:


207

เมื่อเนื้อหาfile.pyมาจากbranch2ที่ไม่ได้ใช้กับbranch1อีกต่อไปมันจะต้องเลือกการเปลี่ยนแปลงบางอย่างและปล่อยให้คนอื่น สำหรับการควบคุมทั้งหมดให้ทำการผสานแบบโต้ตอบโดยใช้--patchสวิตช์:

$ git checkout --patch branch2 file.py

ส่วนโหมดโต้ตอบในหน้า man สำหรับgit-add(1)อธิบายถึงคีย์ที่จะใช้:

y - stage this hunk
n - do not stage this hunk
q - quit; do not stage this hunk nor any of the remaining ones
a - stage this hunk and all later hunks in the file
d - do not stage this hunk nor any of the later hunks in the file
g - select a hunk to go to
/ - search for a hunk matching the given regex
j - leave this hunk undecided, see next undecided hunk
J - leave this hunk undecided, see next hunk
k - leave this hunk undecided, see previous undecided hunk
K - leave this hunk undecided, see previous hunk
s - split the current hunk into smaller hunks
e - manually edit the current hunk
? - print help

คำสั่ง split มีประโยชน์อย่างยิ่ง


3
เราจะใช้โปรแกรมปะแก้และในเวลาเดียวกันใช้เครื่องมือผสานได้อย่างไร แทนสิ่งสำคัญ
กาเบรียล

@ กาเบรียลฉันใช้ Git แม้จะมีไฟล์แพทช์และ tarballs เพราะมันง่ายมากที่จะสร้าง repo ( git init <dir>) และในที่สุดก็ทิ้งมันไป ( rm -r <dir>)
pdp

105

แม้ว่าจะไม่ใช่การผสานต่อบางครั้งเนื้อหาทั้งหมดของไฟล์อื่นในสาขาอื่นเป็นสิ่งจำเป็น โพสต์บล็อกของ Jason Rudolph ให้วิธีง่ายๆในการคัดลอกไฟล์จากสาขาหนึ่งไปอีกสาขาหนึ่ง ใช้เทคนิคดังต่อไปนี้:

$ git checkout branch1 # ensure in branch1 is checked out and active
$ git checkout branch2 file.py

ตอนนี้file.pyขณะนี้อยู่ในbranch1


91
ง่าย แต่ที่ไม่จริงผสาน มันเพิ่งเขียนทับfile.pyสิ่งที่อยู่ในสาขา 2
Greg Hewgill

ถ้าคุณรวมไฟล์กลับจาก branch1 ถึง branch2 คุณจะได้รับความขัดแย้ง!
อาเมียร์

สิ่งนี้ยังคงก่อให้เกิดประวัติศาสตร์หรือไม่?
C2H50H

18

ไม่มีคำตอบปัจจุบันอื่นใดที่จริงจะ "ผสาน" ไฟล์ราวกับว่าคุณกำลังใช้คำสั่งผสาน (อย่างดีที่สุดพวกเขาจะต้องให้คุณเลือก diffs ด้วยตนเอง) หากคุณต้องการใช้ประโยชน์จากการผสานโดยใช้ข้อมูลจากบรรพบุรุษร่วมกันคุณสามารถทำตามขั้นตอนตามที่พบในส่วน"การผสานขั้นสูง"ของ git คู่มืออ้างอิง.

สำหรับโปรโตคอลนี้ฉันสมมติว่าคุณต้องการรวมไฟล์ 'path / to / file.txt' จาก Origin / master เข้ากับ HEAD - แก้ไขตามความเหมาะสม (คุณไม่จำเป็นต้องอยู่ในไดเรกทอรีบนสุดของที่เก็บ แต่ช่วยได้)

# Find the merge base SHA1 (the common ancestor) for the two commits:
git merge-base HEAD origin/master

# Get the contents of the files at each stage
git show <merge-base SHA1>:path/to/file.txt > ./file.common.txt
git show HEAD:path/to/file.txt > ./file.ours.txt
git show origin/master:path/to/file.txt > ./file.theirs.txt

# You can pre-edit any of the files (e.g. run a formatter on it), if you want.

# Merge the files
git merge-file -p ./file.ours.txt ./file.common.txt ./file.theirs.txt > ./file.merged.txt

# Resolve merge conflicts in ./file.merged.txt
# Copy the merged version to the destination
# Clean up the intermediate files

ไฟล์ git mergeควรใช้การตั้งค่าการผสานเริ่มต้นสำหรับการจัดรูปแบบและสิ่งที่คล้ายกัน

นอกจากนี้โปรดทราบว่าหาก "ของเรา" เป็นรุ่นคัดลอกที่ใช้งานได้และคุณไม่ต้องการระมัดระวังมากเกินไปคุณสามารถใช้งานไฟล์ได้โดยตรง:

git merge-base HEAD origin/master
git show <merge-base SHA1>:path/to/file.txt > ./file.common.txt
git show origin/master:path/to/file.txt > ./file.theirs.txt
git merge-file path/to/file.txt ./file.common.txt ./file.theirs.txt

15

การปรับเปลี่ยนทั้งหมดเป็นไปfile.pyในbranch2การกระทำของตนเองแยกจากการแก้ไขไฟล์อื่น ๆ ? ถ้าเป็นเช่นนั้นคุณสามารถcherry-pickเปลี่ยนแปลงได้โดยง่าย:

git checkout branch1
git cherry-pick <commit-with-changes-to-file.py>

มิฉะนั้นmergeจะไม่สามารถใช้งานได้กับแต่ละพา ธ ... คุณอาจสร้างgit diffแพทช์file.pyการเปลี่ยนแปลงจากbranch2และgit applyไปที่branch1:

git checkout branch2
git diff <base-commit-before-changes-to-file.py> -- file.py > my.patch
git checkout branch1
git apply my.patch

8

คุณสามารถstashและstash popไฟล์:

git checkout branch1
git checkout branch2 file.py
git stash
git checkout branch1
git stash pop

สิ่งนี้จะเขียนทับ branch1 / file.py ด้วยเนื้อหาของ branch2 / file.py แทนการรวมที่ควรเพิ่มความขัดแย้งในการผสานเพื่อแก้ไข
plumSemPy

2

หากต้องการรวมการเปลี่ยนแปลงจาก branch2 file.pyเท่านั้นให้ทำการเปลี่ยนแปลงอื่น ๆ หายไป

git checkout -B wip branch2
git read-tree branch1
git checkout branch2 file.py
git commit -m'merging only file.py history from branch2 into branch1'
git checkout branch1
git merge wip

ผสานจะไม่แม้แต่จะดูไฟล์อื่น ๆ คุณอาจต้องใส่เครื่องหมาย '-f' หากต้นไม้แตกต่างกันพอ

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

git checkout -B wip `git merge-base branch1 branch2`

ในกรณีนี้ข้อความการส่งข้อความควรจะเป็นเช่นกัน

git commit -m"merging only $(git rev-parse branch2):file.py into branch1"

0

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

git merge <other-branch>
cp file-to-merge file-to-merge.example
git reset --hard HEAD (or HEAD^1 if no conflicts happen)
cp file-to-merge.example file-to-merge

0

สิ่งที่ฉันทำเป็นคู่มือเล็กน้อย แต่ฉัน:

  1. ผสานสาขาตามปกติ คืนค่าการผสานด้วยrevert;
  2. ตรวจสอบไฟล์ทั้งหมดของฉันไปHEAD~1ที่นั่นคือสถานะของพวกเขาในการรวมการกระทำ;
  3. ปฏิเสธการกระทำของฉันเพื่อซ่อนการแฮ็กเกอร์นี้จากประวัติการกระทำ

น่าเกลียด? ใช่. จำง่ายไหม ใช่แล้ว

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