Git rebase: ความขัดแย้งยังคงปิดกั้นความคืบหน้า


120

ฉันมีสาขาคอมไพล์ (เรียกว่า v4) ซึ่งสร้างจากมาสเตอร์เมื่อวานนี้ มีการเปลี่ยนแปลงหลักสองสามอย่างที่ฉันต้องการเข้าสู่ v4 ดังนั้นใน v4 ฉันพยายามทำ rebase จาก master และไฟล์หนึ่งก็ทำให้สิ่งต่าง ๆ เกิดขึ้น: ไฟล์ข้อความบรรทัดเดียวที่มีหมายเลขเวอร์ชัน ไฟล์นี้app/views/common/version.txtซึ่งก่อนทำการ rebasing จะมีข้อความนี้:

v1.4-alpha-02

นี่คือสิ่งที่ฉันกำลังทำ:

> git rebase master
First, rewinding head to replay your work on top of it...
Applying: new version, new branch
error: patch failed: app/views/common/version.txt:1
error: app/views/common/version.txt: patch does not apply
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
Auto-merging app/views/common/version.txt
CONFLICT (content): Merge conflict in app/views/common/version.txt
Failed to merge in the changes.
Patch failed at 0001 new version, new branch

When you have resolved this problem run "git rebase --continue".
If you would prefer to skip this patch, instead run "git rebase --skip".
To restore the original branch and stop rebasing run "git rebase --abort".

version.txtขณะนี้มีลักษณะเช่นนี้

<<<<<<< HEAD:app/views/common/version.txt
v1.4-alpha-02
=======
v1.4-alpha-01
>>>>>>> new version, new branch:app/views/common/version.txt

ดังนั้นฉันจัดมันให้เรียบร้อยและดูเหมือนตอนนี้:

v1.4-alpha-02

จากนั้นฉันก็พยายามดำเนินการต่อ: ตอนแรกฉันลองกระทำ:

> git commit -a -m "merged"
# Not currently on any branch.
nothing to commit (working directory clean)

ไม่มีโชคที่นั่น ดังนั้นฉันพยายามเพิ่มไฟล์:

git add app/views/common/version.txt

ไม่มีการตอบสนอง ฉันเดาว่าไม่มีข่าวดี ดังนั้นฉันพยายามดำเนินการต่อ:

> git rebase --continue
Applying: new version, new branch
No changes - did you forget to use 'git add'?

When you have resolved this problem run "git rebase --continue".
If you would prefer to skip this patch, instead run "git rebase --skip".
To restore the original branch and stop rebasing run "git rebase --abort".

เมื่อมาถึงจุดนี้หลังจากวนเวียนอยู่กับสิ่งนี้ฉันก็แทบจะสะบัดหัวออกจากโต๊ะทำงาน

เกิดอะไรขึ้นที่นี่? ผมทำอะไรผิดหรือเปล่า? ใครช่วยตั้งให้ฉันตรง

แก้ไข - สำหรับ unutbu

ฉันเปลี่ยนไฟล์ตามที่คุณแนะนำและได้รับข้อผิดพลาดเดียวกัน:

> git rebase master
First, rewinding head to replay your work on top of it...
Applying: new version, new branch
error: patch failed: app/views/common/version.txt:1
error: app/views/common/version.txt: patch does not apply
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
Auto-merging app/views/common/version.txt
CONFLICT (content): Merge conflict in app/views/common/version.txt
Failed to merge in the changes.
Patch failed at 0001 new version, new branch

When you have resolved this problem run "git rebase --continue".
If you would prefer to skip this patch, instead run "git rebase --skip".
To restore the original branch and stop rebasing run "git rebase --abort".

10
ขอบคุณที่ถามคำถามนี้ .. ฉันเจอปัญหาเดียวกัน
เป๊ะ

6
คงจะดีถ้าคุณยืนยันบางคำตอบ
Holms

3
@MaxWilliams ผมคิดว่าคุณ (เช่นฉัน) ต้องตีความผิด @unutbu 's คำแนะนำ: 1) แรกที่คุณใช้git rebase master และปล่อยให้มันล้มเหลว ; 2) จากนั้นคุณแก้ไขversion.txtและทำให้มันควรจะดูที่จุดนั้นและบันทึกการแก้ไข; 3) แล้วคุณgit add .../version.txt; 4) แล้วคุณทำgit rebase --continue( ไม่ 'กระทำ' )! หากrebase --continueประสบความสำเร็จที่นี่แสดงว่ามีความมุ่งมั่นแล้ว (ไม่จำเป็นสำหรับgit commitที่นี่!) - ดังนั้นสิ่งที่ต้องทำคือgit push(ถ้าคุณใช้ repo ระยะไกล) หวังว่านี่จะช่วยได้ถ้าฉันทำถูก:)- ไชโย!
sdaau

@MaxWilliams คุณเคยได้รับคำตอบสำหรับสิ่งนี้หรือไม่: ruby-forum.com/topic/187288 (ฉันจะลบสิ่งนี้ทันทีหลังจากตอบกลับหากมีคนอื่นไม่ได้ไปก่อน !!)
atw

คำตอบ:


102

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

คุณสามารถสร้างปัญหานี้ซ้ำในที่เก็บทดสอบ ก่อนอื่นให้สร้างที่เก็บ

$ mkdir failing-merge
$ cd failing-merge
$ git init
Initialized empty Git repository in $HOME/failing-merge/.git/

จากนั้นยอมรับเนื้อหาต้นฉบับของversion.txtในต้นแบบ

$ echo v1.4-alpha-02 > version.txt
$ git add version.txt
$ git commit -m initial
[master (root-commit) 2eef0a5] initial
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 version.txt

สร้างv4สาขาและเปลี่ยนเนื้อหาของversion.txt.

$ git checkout -b v4
Switched to a new branch 'v4'
$ echo v1.4-alpha-03 > version.txt
$ git add version.txt
$ git commit -m v4
[v4 1ef8c9b] v4
 1 files changed, 1 insertions(+), 1 deletions(-)

กลับไปที่masterและเปลี่ยนเนื้อหาversion.txtเพื่อให้เกิดความสับสนระหว่างการปรับฐานใหม่

$ git checkout master
Switched to branch 'master'
$ echo v1.4-alpha-04 > version.txt
$ git add version.txt
$ git commit -m master
[master 7313eb3] master
 1 files changed, 1 insertions(+), 1 deletions(-)

เปลี่ยนกลับไปที่v4branch และลอง rebase มันล้มเหลวด้วยความสับสนversion.txtตามแผนที่วางไว้

$ git checkout v4
Switched to branch 'v4'
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: v4
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
Auto-merging version.txt
CONFLICT (content): Merge conflict in version.txt
Recorded preimage for 'version.txt'
Failed to merge in the changes.
Patch failed at 0001 v4

When you have resolved this problem run "git rebase --continue".
If you would prefer to skip this patch, instead run "git rebase --skip".
To restore the original branch and stop rebasing run "git rebase --abort".
$ cat version.txt
<<<<<<< HEAD
v1.4-alpha-04
=======
v1.4-alpha-03
>>>>>>> v4

เราแก้ปัญหาความขัดแย้งโดยการเลือกเนื้อหาของmaster version.txtเราเพิ่มไฟล์และพยายามสร้างฐานข้อมูลใหม่ต่อไป

$ echo v1.4-alpha-04 > version.txt
$ git add version.txt
$ git rebase --continue 
Applying: v4
No changes - did you forget to use 'git add'?
If there is nothing left to stage, chances are that something else
already introduced the same changes; you might want to skip this patch.

When you have resolved this problem run "git rebase --continue".
If you would prefer to skip this patch, instead run "git rebase --skip".
To restore the original branch and stop rebasing run "git rebase --abort".

มันล้มเหลว! มาดูกันgitว่ามีการเปลี่ยนแปลงอะไรบ้างในที่เก็บของเรา

$ git status
# Not currently on any branch.
nothing to commit (working directory clean)

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

$ git rebase --skip
HEAD is now at 7313eb3 master

คำเตือน : โปรดทราบว่าgit rebase --skipจะยกเลิกการกระทำที่gitพยายามสร้างฐานใหม่ทั้งหมด ในกรณีของเรานี่น่าจะโอเคเนื่องจากgitกำลังบ่นว่านี่เป็นการกระทำที่ว่างเปล่า หากคุณคิดว่าคุณสูญเสียการเปลี่ยนแปลงไปเมื่อ rebase เสร็จสมบูรณ์คุณสามารถใช้git reflogเพื่อรับรหัสการคอมมิตของที่เก็บของคุณก่อนการรีเบสและใช้git reset --hardเพื่อทำให้ดีโปของคุณกลับมาอยู่ในสถานะนั้นได้ (นี่คือการดำเนินการทำลายอีกครั้ง)


4
ขอบคุณที่สละเวลาเขียนคำอธิบายที่ยืดยาว Sylvain! นั่นจะทำให้ชัดเจนขึ้น ฉันคิดว่าฉันมักจะกังวลกับการข้ามแพตช์เพราะรู้สึกว่างานอาจหายไปนั่นคือแพตช์นั้นเกี่ยวข้องกับไฟล์ทั้งหมดที่ได้รับผลกระทบจาก rebase แทนที่จะเป็นเพียงไฟล์เดียวที่มีความขัดแย้ง แพทช์เป็นเพียงการรวมเดียวในไฟล์เดียวหรือไม่?
Max Williams

3
ไม่แพตช์มีความแตกต่างทั้งหมดของไฟล์ทั้งหมดที่แก้ไขในคอมมิตเดียว แต่เมื่อใช้git rebase --skipคุณจะข้ามการกระทำเพียงครั้งเดียว โดยทั่วไปฉันจะออกgit statusก่อนที่จะข้ามคอมมิตเพื่อดูว่าฉันอยู่ในสถานการณ์นี้หรือไม่
Sylvain Defresne

1
ฉันแค่อยากจะสะท้อน Max เพื่อกล่าวขอบคุณที่สละเวลาเขียนคำอธิบายที่ยอดเยี่ยม - ในที่สุดฉันก็เข้าใจว่าทำไมสิ่งนี้จึงเกิดขึ้น ฉันไม่กลัวอีกต่อไปrebase --skip:)
Ben Dolman

1
คำเตือน - หากคุณมีการเปลี่ยนแปลงหลายอย่างในคอมมิตเดียวคุณอาจสูญเสียงานในการทำ git rebase --skip ฉันเพิ่งทำ
Chrissy H

@ChrissyH เว้นแต่คุณจะทำgit reflog purgeหรือgit reflog deleteคุณยังสามารถรับการเปลี่ยนแปลงกลับมาได้โดยใช้git reflogไฟล์. git rebaseพยายามที่จะชำระเงินที่แตกต่างกันกระทำที่อ้างถึงมีหนึ่งของพวกเขาควรจะเป็นของรัฐของต้นไม้ของคุณก่อนที่คุณจะเริ่มต้นทั้งหมด
Sylvain Defresne

23

อ้างจากที่นี่: http://wholemeal.co.nz/node/9

ฮะ?!? ไม่ฉันไม่ลืมที่จะใช้ git add ฉันทำมัน ... เหมือน ... 2 วินาทีที่แล้ว!

ปรากฎว่าเนื่องจากไม่มีการเปลี่ยนแปลงจาก patch git จึงสงสัยว่ามีบางอย่างผิดปกติ Git คาดว่าจะมีการใช้โปรแกรมแก้ไข แต่ไฟล์ยังคงไม่เปลี่ยนแปลง

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

$ git rebase --skip

หลังจากที่ฉันใช้ git mergetool และแก้ไขการเปลี่ยนแปลงจากนั้นเพิ่มและยืนยันแล้วฉันก็ป้อน <code> git rebase --skip </code> ในขณะที่ 'ไม่ได้อยู่ในสาขาใด ๆ ' และทุกอย่างได้รับการแก้ไข ขอบคุณ!
geerlingguy

จริงๆแล้วฉันคิดว่ามันเป็นการรวมกันของการรัน git mergetool อย่างต่อเนื่องจากนั้น git rebase --continue จากนั้นก็ git mergetool ฯลฯ ซึ่งในที่สุดก็แก้ไขสถานการณ์ของฉันได้
geerlingguy

6

ข้อความแสดงข้อผิดพลาดนั้นเป็นผลมาจากgit commit -a -m "merged"ไฟล์. หากคุณเพิ่งแก้ไขไฟล์ให้เรียกใช้git add <file>และgit rebase --continueควรใช้งานได้ดี git rebase --continueกำลังพยายามทำการคอมมิต แต่พบว่าไม่มีการเปลี่ยนแปลงที่รอดำเนินการให้กระทำ (เนื่องจากคุณได้ดำเนินการไปแล้ว)


1
นี่ดูเหมือนจะเป็นข้อตกลงที่ดีกว่าการข้ามขั้นตอนอย่างน้อยก็ในกรณีทั่วไป ฉันแปลกใจที่ไม่ได้ระบุว่าเป็นคำตอบที่ดีที่สุด
มรกต

1
@EmeraldD. ใช้ไม่ได้. การแก้ไขไฟล์และเรียกใช้git add <file>ไม่สามารถแก้ปัญหาได้ git rebase --continue ยังคงรายงานNo changes - did you forget to use 'git add'?
Pacerier

6

เปลี่ยน app / views / common / version.txt เป็น

v1.4-alpha-01

ณ จุดนี้ใน rebase โปรดจำไว้ว่าคุณกำลังแก้ไขข้อขัดแย้งในการผสานเพื่อแสดงความก้าวหน้าของสาขาที่ไม่ใช่สาขาหลัก

ดังนั้นในการเปลี่ยนจาก

      A---B---C topic
     /
D---E---F---G master

ถึง

              A*--B*--C* topic
             /
D---E---F---G master

ความขัดแย้งที่คุณกำลังแก้ไขอยู่ในวิธีสร้าง A * ในสาขาหัวข้อ

ดังนั้นหลังจากทำgit rebase --abortคำสั่งควรเป็น

git checkout topic
git rebase master
< make edits to resolve conflicts >
git add .
git rebase --continue

3
ขอบคุณ Unutbu ฉันลองแล้ว แต่โชคไม่ดี: ดู OP สำหรับการแก้ไขใหม่ ไชโย
Max Williams

4

พฤติกรรมที่คุณเห็นไม่ใช่สิ่งที่ฉันคาดหวังจากฐานข้อมูลทั่วไปที่มีเพียงความขัดแย้งนี้ พิจารณาใช้สาขาแยกต่างหากเพื่อทำการ rebase นี้ (โดยเฉพาะอย่างยิ่งถ้าคุณได้ผลักดันคอมมิตจากระยะไกลซึ่งคุณกำลังส่งต่ออย่างรวดเร็ว) นอกจากนี้ยังgit mergetoolมีประโยชน์ในการแก้ไขความขัดแย้งและอย่าลืมออกกgit add.

ในตัวอย่างขั้นต่ำนี้ rebase ทำงานตามที่คาดไว้ คุณสามารถให้ตัวอย่างที่แสดงพฤติกรรมที่คุณเห็นได้หรือไม่?

#!/bin/bash

cd /tmp
mkdir rebasetest
cd rebasetest
git init
echo 'v1.0' > version.txt
git add version.txt
git commit -m 'initial commit'
git checkout -b v4
echo 'v1.4-alpha-01' > version.txt
git add version.txt
git commit -m 'created v4'
git checkout master
git merge v4
echo 'v1.4-alpha-01-rc1' > version.txt
git add version.txt
git commit -m 'upped version on master to v1.4-alpha-01-rc1'
git checkout v4
echo 'v1.4-alpha-02' > version.txt
git add version.txt
git commit -m 'starting work on alpha-02'

git rebase master
echo 'v1.4-alpha-02' > version.txt
git add version.txt
git rebase --continue

4

นี่คือแนวคิดบางส่วน:

  • ก่อนที่จะเริ่ม rebase ตรวจสอบให้แน่ใจว่าคุณไม่ได้อยู่ตรงกลางของ rebase หรือ am ทำ:rm -rf .git/rebase-apply
  • เล็กน้อยที่คุณพูดถึงฉันไม่เข้าใจ: "แล้วลองดำเนินการต่อ: ตอนแรกฉันลองคอมมิต:" ... ผูกมัดทำไม? ในช่วงกลางของ rebase ฉันคิดว่าคุณควร "git add" หลังจากที่คุณจัดระเบียบเรียบร้อยแล้วหรือ "git rm" เพื่อโยนการเปลี่ยนแปลงหรือยืนยันการลบไฟล์ อาจจะทำให้บางอย่างยุ่งเหยิง?
  • ลองผสานแทนการสร้างฐานใหม่
  • ลองใช้แนวคิดของ Ethan Rowe
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.