ฉันจะรวมการเปลี่ยนแปลงกับไฟล์เดียวแทนที่จะรวมการคอมมิท


383

ฉันมีสองสาขา (A และ B) และฉันต้องการรวมไฟล์เดียวจากสาขา A กับไฟล์เดียวที่เกี่ยวข้องจาก Branch B


2
กล่าวถึงที่นี่แล้วstackoverflow.com/questions/449541/...
โพซิตรอน

27
ส่วนใหญ่ของการตอบสนองในการโพสต์อื่น ๆ ที่เกี่ยวกับวิธีการคัดเลือกผสานกระทำไม่ไฟล์ ทำให้คำตอบที่เลือกไม่ถูกต้อง คำถามยังไม่ได้ตอบ


คำตอบนี้เป็นวิธีที่จะไป IMO git diff branch_name > patch git apply patch. stackoverflow.com/a/9473543/1091853
blamb

คำตอบ:


631

ฉันเจอปัญหาเดียวกัน เพื่อความแม่นยำฉันมีสองสาขาAและBมีไฟล์เดียวกัน แต่มีอินเตอร์เฟสการเขียนโปรแกรมที่แตกต่างกันในบางไฟล์ ตอนนี้วิธีการของไฟล์fซึ่งเป็นอิสระจากความแตกต่างของส่วนต่อประสานในสองสาขาได้เปลี่ยนไปในสาขาBแต่การเปลี่ยนแปลงสำคัญสำหรับทั้งสองสาขา ดังนั้นฉันต้องการที่จะผสานไฟล์เพียงfสาขาBลงในแฟ้มของสาขาfA

คำสั่งง่าย ๆ แก้ปัญหาให้ฉันแล้วถ้าฉันคิดว่าการเปลี่ยนแปลงทั้งหมดเกิดขึ้นในทั้งสองสาขาAและB:

git checkout A

git checkout --patch B f

คำสั่งแรกสวิทช์ลงในสาขาAลงที่ฉันต้องการที่จะผสานB's fรุ่นของแฟ้ม คำสั่งที่สองแพทช์ไฟล์fกับfของของHEAD Bคุณสามารถยอมรับ / ทิ้งส่วนหนึ่งส่วนของแพทช์ แทนที่จะBคุณสามารถระบุใด ๆ HEADที่กระทำอยู่ที่นี่ก็ไม่ได้จะต้องมีการ

แก้ไขโดยชุมชน : ถ้าแฟ้มfบนBไม่มีอยู่บนAยังแล้วละเว้น--patchตัวเลือก มิฉะนั้นคุณจะได้รับ "ไม่มีการเปลี่ยนแปลง" ข่าวสาร


10
ใช้งานได้เฉพาะในกรณีที่คุณต้องการอัปเดตไฟล์ ถ้าฉันต้องการเพิ่มไฟล์ใหม่จากสาขา B ไปยังสาขา A
Umair A.

25
@UmairAshraf คุณควรจะสามารถเพิ่มไฟล์ใหม่จาก B ถึง A โดยการลบตัวเลือก --patch
bbak

9
อืม ... เมื่อฉันลองทำสิ่งนี้ฉันจะได้รับข้อความ "ไม่มีการเปลี่ยนแปลง" แต่มีการเปลี่ยนแปลงอย่างชัดเจน ตกลงฉันต้องอยู่ในโฟลเดอร์ที่มีไฟล์ที่เกี่ยวข้อง แก้ไข: นี่อาจเป็นทางออกที่ฉันโปรดปรานสำหรับปัญหาที่ฉันเคยเห็นใน stackoverflow :-D
bot_bot

2
ฉันต้องใช้git checkout --patch B -- fเพื่อให้เรื่องนี้ทำงาน
user545424

8
เพียงแค่เพิ่มว่าถ้าคุณมีการเปลี่ยนแปลงหลายครั้ง (hunks)ในไฟล์และคุณต้องการที่จะเวทีพวกเขาทั้งหมดคุณสามารถกดaในช่วงโต้ตอบโต้ตอบแทนการกดyทุกครั้ง หรือใช้git checkout B -- fคำสั่งแทน
Dmitry Gonchar

17

นี่คือสิ่งที่ฉันทำในสถานการณ์เหล่านี้ มันเป็นรถถัง แต่มันใช้งานได้ดีสำหรับฉัน

  1. สร้างสาขาอื่นตามสาขาการทำงานของคุณ
  2. git pull / git รวมการแก้ไข (SHA1) ซึ่งมีไฟล์ที่คุณต้องการคัดลอก ดังนั้นสิ่งนี้จะรวมการเปลี่ยนแปลงทั้งหมดของคุณ แต่เราใช้เฉพาะสาขานี้เพื่อคว้าไฟล์เดียว
  3. แก้ไขข้อขัดแย้งใด ๆ ฯลฯ ตรวจสอบไฟล์ของคุณ
  4. ชำระเงินสาขาที่ทำงานของคุณ
  5. ชำระเงินไฟล์ที่กระทำจากการรวมของคุณ
  6. กระทำมัน

ฉันพยายามแก้ไขและสถานการณ์ของฉันมันน่าเกลียดเกินไป ดังนั้นในระยะสั้นมันจะเป็นดังนี้:

สาขาการทำงาน: สาขาทดลอง: B (มี file.txt ซึ่งมีการเปลี่ยนแปลงที่ฉันต้องการพับใน)

git checkout A

สร้างสาขาใหม่โดยใช้ A:

git checkout -b tempAB

รวม B เข้ากับเทมเพลต

git merge B

คัดลอกแฮช sha1 ของการรวม:

git log

commit 8dad944210dfb901695975886737dc35614fa94e
Merge: ea3aec1 0f76e61
Author: matthewe <matthewe@matthewe.com>
Date:   Wed Oct 3 15:13:24 2012 -0700

Merge branch 'B' into tempAB

ชำระเงินสาขาที่ทำงานของคุณ:

git checkout A

ชำระเงินไฟล์ที่แก้ไขแล้วของคุณ:

git checkout 7e65b5a52e5f8b1979d75dffbbe4f7ee7dad5017 file.txt

และที่นั่นคุณควรจะมีมัน ยอมรับผลลัพธ์ของคุณ


3
ดังนั้นเราต้องทำทั้งหมดนี้เพื่อรวมไฟล์เดียว? การคัดลอกและวางไฟล์ในสาขาอื่นจะไม่ใช่เรื่องง่ายกว่านี้หรือไม่
Robin

1
@Robin อาจไม่ได้เนื่องจากการรวมกันทำให้การเปลี่ยนแปลงในไฟล์นั้นแตกต่างกันระหว่างสาขา A และ B การคัดลอกไฟล์จะเขียนทับความแตกต่างเพิ่มเติมระหว่างสาขางานของคุณ A และสิ่งที่คุณต้องการนำเข้าจาก B ซึ่งอาจไม่มี รายการ / การแก้ไขเหล่านั้น เช่นผู้ต้องสงสัยAได้หันเหความสนใจจากBเริ่มต้นด้วยวิธีอื่น การคัดลอกจะแทนที่ความแตกต่างเหล่านั้น
blamb

13

สิ่งนี้ใช้ difftool ภายในของคอมไพล์ อาจจะเป็นงานเล็ก ๆ น้อย ๆ ที่ต้องทำ แต่ตรงไปตรงมา

#First checkout the branch you want to merge into
git checkout <branch_to_merge_into>

#Then checkout the file from the branch you want to merge from
git checkout <branch_to_merge_from> -- <file> 

#Then you have to unstage that file to be able to use difftool
git reset HEAD <file> 

#Now use difftool to chose which lines to keep. Click on the mergebutton in difftool
git difftool

#Save the file in difftool and you should be done.

1
ในการชี้แจงการใช้--(ป้ายกำกับอาร์กิวเมนต์ที่ว่างเปล่า) ให้ใช้เอกสารการชำระเงิน git: ARGUMENT DISAMBIGUATIONพูดว่า: "ใช้git checkout -- <pathspec>ถ้าคุณต้องการเช็คเอาต์พา ธ เหล่านี้ออกจากดัชนี" นี่เป็นเพราะคุณสามารถมีทั้งสาขาและไฟล์ / พา ธ ด้วยชื่อเดียวกัน ในกรณีเช่นนี้แทนที่จะขอให้คุณแก้ความสงสัยว่าควรตรวจสอบสาขาหรือเส้นทางเมื่อมีอยู่ทั้งคู่หรือไม่ git จะเลือกเช็คเอาต์สาขาตามค่าเริ่มต้น อย่างไรก็ตามหาก--นำหน้าคอมไพล์จะเช็กเอาต์ไฟล์ / พา ธ แทน
SherylHohman

8

ฉันพบวิธีการนี้ง่ายและมีประโยชน์: วิธี "ผสาน" ไฟล์เฉพาะจากสาขาอื่น

เมื่อปรากฎว่าเราพยายามหนักเกินไป การชำระเงินคอมไพล์เพื่อนที่ดีของเราเป็นเครื่องมือที่เหมาะสมสำหรับงาน

git checkout source_branch <paths>...

เราสามารถให้ชื่อของสาขาฟีเจอร์ A และเช็คเอาต์ไปยังไฟล์เฉพาะที่เราต้องการเพิ่มไปยังสาขาหลักของเรา

โปรดอ่านบทความทั้งหมดเพื่อความเข้าใจที่มากขึ้น


2
สิ่งนี้จะเขียนทับไฟล์ แต่จะไม่รวมเข้าด้วยกัน
Alex G

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

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

แนวคิดนี้มาจากปี 2009 มีโอกาสเป็นรุ่นใหม่ของ git ที่ทำงานแตกต่างกันและต้องการ -p หรืออย่างอื่น แต่กลับมาตอนที่ฉันโพสต์มันใช้งานได้สำหรับฉัน แต่อีกครั้งฉันอาจไม่สนใจว่าไฟล์ถูกแทนที่ เวอร์ชันล่าสุดคือสิ่งที่ฉันต้องการ
Pawel Cioch


3

คำสั่งต่อไปนี้จะ (1) เปรียบเทียบไฟล์ของสาขาที่ถูกต้องกับมาสเตอร์ (2) แบบโต้ตอบถามคุณว่าการแก้ไขใดที่จะนำไปใช้

git checkout --patch master


0

การแก้ไขของฉันถูกปฏิเสธดังนั้นฉันจึงแนบวิธีจัดการกับการรวมการเปลี่ยนแปลงจากสาขาระยะไกลที่นี่

หากคุณต้องทำหลังจากผสานไม่ถูกต้องคุณสามารถทำสิ่งนี้:

# If you did a git pull and it broke something, do this first
# Find the one before the merge, copy the SHA1
git reflog
git reset --hard <sha1>

# Get remote updates but DONT auto merge it
git fetch github 

# Checkout to your mainline so your branch is correct.
git checkout develop 

# Make a new branch where you'll be applying matches
git checkout -b manual-merge-github-develop

# Apply your patches
git checkout --patch github/develop path/to/file
...

# Merge changes back in
git checkout develop
git merge manual-merge-github-develop # optionally add --no-ff

# You'll probably have to
git push -f # make sure you know what you're doing.

0

สมมติว่า B เป็นสาขาปัจจุบัน:

$ git diff A <file-path> > patch.tmp
$ git apply patch.tmp -R

โปรดทราบว่านี่ใช้การเปลี่ยนแปลงกับไฟล์ในเครื่อง คุณจะต้องกระทำในภายหลัง


สำหรับผมนี้สร้างerror: <file-path>: already exists in working directory
Kontur

คุณควรระบุไฟล์หรือพา ธ ไฟล์ที่ไดเรกทอรีปัจจุบัน ฉันใช้git diff Branch_A <file-path, filename> -- hash_commit > file_name.temp
R.Chatsiri

0

คุณสามารถเช็คเอาต์ไฟล์เวอร์ชันเก่าเพื่อรวมบันทึกไว้ในชื่ออื่นจากนั้นเรียกใช้เครื่องมือผสานที่อยู่ในไฟล์สองไฟล์

เช่น.

git show B:src/common/store.ts > /tmp/store.ts (โดยที่ B คือชื่อสาขา / กระทำ / แท็ก)

meld src/common/store.ts /tmp/store.ts


0

ฉันจะทำตาม

git format-patch branch_old..branch_new file

สิ่งนี้จะสร้างแพตช์สำหรับไฟล์

ติดตั้ง patch ที่ target branch_old

git am blahblah.patch


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