ฉันจะรับเอาต์พุตที่เข้ากันได้กับ patch จาก git-diff หรือไม่


160

ฉันกำลังทำสิ่งที่ผิดง่ายมาก ฉันกำลังเตรียมไฟล์ปะไฟล์ธรรมดาดังนั้นฉันสามารถนำการเปลี่ยนแปลงมาใช้ใหม่ได้:

$ git diff > before
$ git diff something_here > save.patch
$ git checkout . 
$ patch < save.patch
$ git diff > after
$ diff before after
$

ด้วยความsomething_here ว่างเปล่ามันใช้งานได้เกือบ แต่ชื่อไฟล์ไม่ถูกต้อง ฉันคิดว่าฉันแค่ฉันไม่มีตัวเลือก

ในชีวิตจริงฉันจะรวมหลังจากการเช็คเอาต์ดังนั้นแพทช์อาจล้มเหลว แต่คุณเห็นสิ่งที่ฉันได้รับ

แก้ไข ความผิดของฉันที่นี่เพื่อถามคำถามที่ผิด คำถามจริงคือฉันต้องการบันทึกการเปลี่ยนแปลงของฉันทำการผสานแล้วนำการเปลี่ยนแปลงไปใช้อีกครั้งถ้าเป็นไปได้ ฉันถามผิดวิธีเพราะฉันคุ้นเคยกับการใช้ patch เพื่อแก้ปัญหาต่าง ๆ เหล่านี้และgit diffดูเหมือนว่าเป็นสิ่งที่ฉันต้องการทำ

ความคิดเห็นของ Charles Baile มีคำตอบที่ถูกต้อง สำหรับฉันการใช้ git เป็นสิ่งที่ถูกต้อง (git-stash ดูมีน้ำหนักมากเกินกว่าที่ฉันต้องการและการรีบูทและมัดรวมกันเกินกว่าระดับความสามารถในปัจจุบันของฉัน) ฉันจะยอมรับคำตอบที่ Charles มอบให้ (เพราะคุณ ไม่สามารถยอมรับความคิดเห็น) ขอบคุณสำหรับคำแนะนำทั้งหมด.

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

$ git stash
$ git merge
$ git stash pop

8
มีเหตุผลที่คุณต้องการเฉพาะจะใช้ใด ๆpatchมากกว่าgit apply?
CB Bailey

3
และถึงตอนนั้นคุณต้องการแพทช์มากกว่าสิ่งที่เหมือนgit stashหรือเครื่องมือคอมไพล์อื่น ๆ หรือไม่
CB Bailey

3
โพสต์ - แก้ไขฉันคิดว่านั่นgit stashเป็นทางออกที่ง่ายที่สุดสำหรับสิ่งที่คุณพยายามทำ
CB Bailey

1
@ Malvolio: แน่นอนคุณไม่ต้องคิดชื่อไฟล์ชั่วคราวเพื่อเก็บ patch ของคุณไว้
CB Bailey

4
@Charlse บางครั้งคุณต้องส่งปะให้คนที่ไม่มีที่เก็บ git ทั้งหมด git-svnตัวอย่างเช่นถ้าใช้
Elazar Leibovich

คำตอบ:


139

หากคุณต้องการใช้โปรแกรมแก้ไขคุณต้องลบส่วนa/ b/นำหน้าที่ใช้โดยค่าเริ่มต้น คุณสามารถทำได้ด้วย--no-prefixตัวเลือก (คุณสามารถทำได้ด้วย-pตัวเลือกของ patch ):

git diff --no-prefix [<other git-diff arguments>]

โดยปกติ แต่มันเป็นเรื่องง่ายที่จะใช้ตรงแล้วใช้ออกไปฟีดgit diffgit apply

ส่วนใหญ่ฉันพยายามหลีกเลี่ยงการใช้โปรแกรมแก้ไขข้อความ โดยปกติแล้วหนึ่งคอมมิชชันชั่วคราวที่รวมกับการรีบูตgit stashและการรวมกลุ่มนั้นง่ายต่อการจัดการ

สำหรับกรณีการใช้งานของคุณฉันคิดว่าstashเหมาะสมที่สุด

# save uncommitted changes
git stash

# do a merge or some other operation
git merge some-branch

# re-apply changes, removing stash if successful
# (you may be asked to resolve conflicts).
git stash pop

7
git diff --no-prefix master > diff.patchและจากนั้นgit checkout master patch -p0 < diff.patch
Natim

1
@Natim เพื่อความปลอดภัยสูงสุดฉันจะแนะนำให้ใช้patch --dry-run < diff.patchก่อนที่จะออกคำสั่งสุดท้าย
ᴠɪɴᴄᴇɴᴛ

1
@ ᴠɪɴᴄᴇɴᴛประโยชน์ของการทำเช่นนั้นคืออะไร? เนื่องจากเราใช้คอมไพล์เราจึงไม่น่าจะสูญเสียสิ่งใดเลย
Natim

1
@Natim อย่างที่ฉันพูดเพียงเพื่อความปลอดภัยขั้นสูงสุดไม่จำเป็นต้องยกเลิกสิ่งใดในกรณีที่เกิดข้อผิดพลาด ฉันยังคิดถึงคนที่อ่านบทความนี้และต้องการใช้งานpatchนอกระบบคอมไพล์ (อาจใช้ไฟล์แพทช์ที่สร้างขึ้นdiff) ในกรณีที่ใช้งานทั่วไปมากกว่า
ᴠɪɴᴄᴇɴᴛ

เพื่อที่จะรวมใหม่ไฟล์ในแพทช์ของคุณคุณต้องนอกจากนี้ยังรวมถึง "คอมไพล์ diff --no-คำนำหน้า --cached" ในแพทช์ อาจจะมีวิธีที่ดีกว่า
jamshid

219

เพียงแค่ใช้-p1: คุณจะต้องใช้-p0ใน--no-prefixกรณีต่อไปดังนั้นคุณสามารถละทิ้ง--no-prefixและใช้-p1:

$ git diff > save.patch
$ patch -p1 < save.patch

$ git diff --no-prefix > save.patch
$ patch -p0 < save.patch

1
หากคุณสงสัยว่าทำไมคนที่เอกสารผลรวมมันได้เป็นอย่างดี - แหล่งที่มา
tutuDajuju

3
สิ่งนี้จะไม่ทำงานกับการเปลี่ยนชื่อ git diffเอาต์พุตบรรทัดที่patchละเว้น git applyเป็นวิธีที่จะไป
hraban

17

git diffs มีเซ็กเมนต์พา ธ พิเศษที่เพิ่มเติมเข้ากับพา ธ ไฟล์ คุณสามารถตัดรายการนี้ในพา ธ โดยระบุ -p1 ด้วย patch เช่น:

patch -p1 < save.patch

10
  1. ฉันบันทึกส่วนต่างของไดเรกทอรีปัจจุบัน (รวมถึงไฟล์ที่ไม่มีข้อผูกมัด) กับส่วนหัวปัจจุบัน
  2. จากนั้นคุณสามารถส่งsave.patchไฟล์ไปยังที่ใดก็ได้ (รวมถึงไฟล์ไบนารี)
  3. บนเครื่องเป้าหมายของคุณให้ใช้โปรแกรมแก้ไขโดยใช้ git apply <file>

หมายเหตุ: มันเป็นไฟล์ที่จัดเตรียมไว้ในปัจจุบันด้วย

$ git diff --binary --staged HEAD > save.patch
$ git reset --hard
$ <transport it>
$ git apply save.patch

ฮ่า ๆ ๆ ๆ มันสนุก. ฉันถามคำถามนี้เมื่อสี่ปีก่อนและวิธีที่ฉันทำสิ่งนี้ได้วิวัฒนาการมา แต่ถ้าคุณถามฉันเมื่อวานว่าจะทำอย่างไรฉันจะได้รับคำตอบจากคุณและบอกว่าฉันได้คำตอบจากคำถามนี้ (อันที่จริงผมก็อาจจะใช้เปลือยgit diff > save.patchและgit checkout .แทนการรีเซ็ต แต่ใช่ ...
Malvolio

โอ้ไม่ได้สังเกตอายุ 4 ขวบของมัน: P Btw การรีเซ็ตเป็นเพียงเพื่อแสดงให้เห็นถึงการทำงาน .. ฉันยังไม่เห็นใครใช้git applyหรือทำให้ diff ที่เกี่ยวข้องกับสถานะของคุณและตัวชี้ไปยังการส่งมอบครั้งล่าสุด การทำเพียงgit diffยังไม่ได้ทำอะไรเลย
Matej

git applyใช่ตอนนี้ผมสงสัยว่าผมพบข้อมูลเกี่ยวกับ สิ่งที่git diffเป็น (ฉันคิดว่า) จากการใช้git reset- ความสัมพันธ์ระหว่าง repo, ดัชนีและพื้นที่ทำงานเป็นปัญหา
Malvolio

8

เคล็ดลับที่มีประโยชน์เพื่อหลีกเลี่ยงการสร้างไฟล์ปะแก้ชั่วคราว:

git diff | patch -p1 -d [dst-dir]

สิ่งที่ฉันต้องการ ยังทำงานได้อย่างสมบูรณ์แบบด้วย stashes! git stash show -p stash@{3} | patch -p1 -d [dst-dir]
dtmland
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.