วิธีเชอร์รี่เลือกเฉพาะการเปลี่ยนแปลงสำหรับไฟล์เดียวเท่านั้นไม่ใช่การคอมมิตทั้งหมด


110

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


คำตอบ:


139

คุณมีตัวเลือกต่างๆตามสิ่งที่คุณต้องการบรรลุ:

หากคุณต้องการให้เนื้อหาของไฟล์เหมือนกับสาขาเป้าหมายคุณสามารถใช้git checkout <branch> -- <filename>ไฟล์. อย่างไรก็ตามสิ่งนี้จะไม่ "เลือกเชอร์รี่" การเปลี่ยนแปลงที่เกิดขึ้นในคอมมิตเดียว แต่ใช้สถานะผลลัพธ์ของไฟล์ดังกล่าวเท่านั้น ดังนั้นหากคุณเพิ่มบรรทัดในการคอมมิต แต่การคอมมิตก่อนหน้านั้นเปลี่ยนแปลงมากขึ้นและคุณต้องการเพิ่มบรรทัดนั้นโดยไม่มีการเปลี่ยนแปลงอื่น ๆ การชำระเงินก็ไม่ใช่สิ่งที่คุณต้องการ

มิฉะนั้นหากคุณต้องการใช้โปรแกรมแก้ไขที่แนะนำในการคอมมิตกับไฟล์เดียวคุณมีหลายตัวเลือก คุณสามารถเรียกใช้git cherry-pick -nงานได้เช่นโดยไม่ต้องคอมมิตแก้ไขคอมมิต (ตัวอย่างเช่นรีเซ็ตไฟล์ทั้งหมดโดยใช้git reset -- .และเพิ่มเฉพาะไฟล์ที่คุณต้องการเปลี่ยนโดยใช้git add <filename>เท่านั้น) หรือคุณสามารถสร้างความแตกต่างสำหรับไฟล์และใช้ความแตกต่างจากนั้น:

git diff <branch>^..<branch> -- <filename> | git apply

23

สร้างpatch fileและนำไปใช้

git diff branchname -- filename > patchfile
git apply patchfile

แก้ไข:

เนื่องจากคุณต้องทำการเปลี่ยนแปลงจากคอมมิตให้สร้างแพตช์ดังนี้:

git show sha1 -- filename > patchfile

1
git diff sha1(หรือgit diff branch- ก็เหมือนกันถ้าสาขาชี้ไปที่แฮชเดียวกัน) จะสร้างความแตกต่างของไดเร็กทอรีการทำงานปัจจุบันที่สัมพันธ์กับแฮชนั้นเท่านั้น แต่ไม่ใช่สิ่งที่เปลี่ยนแปลงคอมมิตที่แนะนำด้วยตัวมันเอง
โผล่

แก้ไข. แก้ไขคำตอบแล้ว ขอบคุณ.
Sailesh

1
-1 ที่git checkoutมีชื่อไฟล์เป็นค้อนที่เหมาะสมสำหรับตะปูนี้ ทั้งสองตัวเลือกเหล่านี้มีความซับซ้อนโดยไม่จำเป็น
Rein Henrichs

7
สำหรับกรณีนี้โดยเฉพาะใช่ แต่โดยทั่วไปแล้วหากคุณต้องการเลือกการเปลี่ยนแปลงจากการคอมมิตที่ทำกับไฟล์ใดไฟล์หนึ่งcheckoutจะไม่ทำงานเนื่องจากอาจเกี่ยวข้องกับการเปลี่ยนแปลงก่อนหน้าอื่น ๆ ที่ไม่ต้องการและอาจไม่มีการเปลี่ยนแปลงที่เกิดขึ้นในสาขาปัจจุบัน
Sailesh

11

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

git checkout {<name_of_branch>, commit's SHA} <path to the file> 

นั่นไม่ใช่การเก็บเชอร์รี่


2
คำเตือน: ตามที่ @poke กล่าวในคำตอบของเขาสิ่งนี้ไม่ได้คัดลอกการเปลี่ยนแปลง จะคัดลอกสถานะทั้งหมดของไฟล์ ดังนั้นหากคุณต้องการเพิ่มการเปลี่ยนแปลงของการกระทำลงในไฟล์จากนั้นการทำเครื่องหมายแบบนี้จะทำให้คุณเขียนทับการเปลี่ยนแปลงใหม่ ๆ ที่ไม่ดี
Alexander Bird

7

Git มีทุกอย่างพร้อม :)

เพียงแค่ใช้ git checkout <sha> <path-to-file>


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

6
git checkout the_branch_with_the_change the/path/to/the/file/you/want.extension

วิธีนี้ใช้งานได้ถ้าคุณต้องการให้ไฟล์เดียวจากสาขาอื่นถูกคัดลอกไปยังสาขาการทำงานปัจจุบัน


1
โปรดระวังการเปลี่ยนแปลงที่ทำในไฟล์ที่ไม่ได้อยู่ในเวอร์ชันจากสาขาอื่นจะสูญหายไป
Patrick Schlüter

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

1
เราสามารถใช้ globs (path / *) และระบุมากกว่าหนึ่ง path / file
Todd

1

นี่คือสิ่งที่คุณกำลังมองหา:

git checkout target-branch sha1 path/to/file

sha1 เป็นทางเลือก


12
ไม่ "เลือกการเปลี่ยนแปลงในคอมมิต" ไม่ใช่ "เลือกทั้งไฟล์"
Abyx

1

สิ่งที่ฉันมักจะทำคือการใช้ git ls-tree

แค่ทำ:

git ls-tree -r <commit-id> |grep 'your filename'
# there will be output that shows a SHA1 of your file
git show ${SHA1 of your file} > 'your filename'

สิ่งนี้จะพิมพ์ชื่อไฟล์ทั้งหมดที่ตรงกับ grep ของคุณและให้คีย์ SHA1 ของไฟล์ในคอมมิต

Git show สามารถใช้กับไฟล์ภายนอกสาขาของคุณได้เช่นกัน การใช้>จากเชลล์ของคุณเพื่อไพพ์เอาต์พุตลงในไฟล์ทำให้คุณได้ผลลัพธ์ที่คุณต้องการ


0

คุณสามารถลองทำสิ่งนี้:

git show COMMIT_ID -- path/to/specific-file | git apply

ตัวอย่างเช่น:

git show 3feaf20 -- app/views/home/index.html | git apply

-9
git reset HEAD~1

ย้ายไฟล์ไปไว้ในขั้นตอนก่อนคอมมิต

git stash

ลบออกจากหน่วยความจำ

ตอนนี้สาขาของคุณค่อนข้างสะอาด (เปลี่ยนกลับเป็นคอมมิตก่อนหน้า)

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