วิธีรับไฟล์เดียวจากสาขาอื่น


1262

ฉันใช้คอมไพล์และทำงานในสาขาหลัก app.jsสาขานี้มีไฟล์ที่เรียกว่า

ฉันมีexperimentสาขาที่ฉันทำการเปลี่ยนแปลงมากมายและมีภาระผูกพันมากมาย ตอนนี้ฉันต้องการนำการเปลี่ยนแปลงทั้งหมดที่ทำไปapp.jsจากสาขาexperimentไปmasterเท่านั้น

ฉันจะทำอย่างไร

ฉันไม่ต้องการรวมอีกครั้ง ฉันแค่ต้องการนำการเปลี่ยนแปลงทั้งหมดapp.jsจากexperimentสาขาไปยังmasterสาขา



1
ยกเว้นคำตอบและคนอื่น ๆ ณ วันนี้ตอบวิธีคัดลอกเนื้อหาของไฟล์นั่นคือสิ่งที่ฉันต้องการด้วยตัวเองเมื่อฉันพบสิ่งนั้น อย่างไรก็ตามหากอ่านอย่างชัดเจน Nick ต้องการนำการเปลี่ยนแปลงไม่ใช่ข้อความเต็มและไฟล์masterอาจแตกต่างจากexperimentเช่นสามารถมีการเปลี่ยนแปลงที่ผสานจากสาขาอื่น ๆ ซึ่งจะหายไปในไฟล์ PS ในทางกลับกันเขาไม่ต้องการผสาน แต่เท่าที่ฉันรู้git mergeคำศัพท์นั้นมีไว้สำหรับสาขาเท่านั้นไม่ใช่สำหรับไฟล์ที่เฉพาะเจาะจงดังนั้นจึงไม่มีความขัดแย้งกันที่นี่
Alexei Martianov

คำตอบ:


1600
git checkout master               # first get back to master
git checkout experiment -- app.js # then copy the version of app.js 
                                  # from branch "experiment"

ดูวิธีการเลิกทำการเปลี่ยนแปลงไฟล์เดียวหรือไม่


อัปเดตสิงหาคม 2562 Git 2.23

ด้วยใหม่git switchและgit restoreคำสั่งที่จะ:

git switch master
git restore -s experiment -- app.js

โดยค่าเริ่มต้นต้นไม้การทำงานเท่านั้นที่จะถูกกู้คืน
ถ้าคุณต้องการอัพเดตดัชนีเช่นกัน (หมายถึงกู้คืนเนื้อหาไฟล์และเพิ่มลงในดัชนีในคำสั่งเดียว):

git restore -s experiment --staged --worktree -- app.js
# shorter:
git restore -s experiment -WS -- app.js

ในฐานะที่เป็นJakub Narębskiกล่าวถึงในความคิดเห็น:

git show experiment:path/to/app.js > path/to/app.js

ทำงานเช่นกันยกเว้นว่าตามรายละเอียดในคำถาม SO " วิธีการดึงไฟล์เดียวจากการแก้ไขเฉพาะใน Git? " คุณจะต้องใช้เส้นทางแบบเต็มจากไดเรกทอรีรากของ repo
ดังนั้น path / to / app.js ที่ Jakub ใช้ในตัวอย่างของเขา

ในฐานะที่เป็นFrostyกล่าวถึงในความคิดเห็น:

คุณจะได้รับสถานะล่าสุดของ app.js เท่านั้น

แต่สำหรับgit checkoutหรือgit showคุณสามารถอ้างอิงการแก้ไขใด ๆ ที่คุณต้องการตามที่แสดงในคำถาม SO " การแก้ไขการชำระเงิน git ของไฟล์ใน git gui ":

$ git show $REVISION:$FILENAME
$ git checkout $REVISION -- $FILENAME

จะเหมือนกันคือ $ FILENAME เป็นเส้นทางแบบเต็มของไฟล์ที่มีเวอร์ชัน

$REVISIONสามารถดังแสดงในgit rev-parse:

experiment@{yesterday}:app.js # app.js as it was yesterday 
experiment^:app.js            # app.js on the first commit parent
experiment@{2}:app.js         # app.js two commits ago

และอื่น ๆ

schmijosเพิ่มในความคิดเห็น :

คุณสามารถทำได้จากที่เก็บของ:

git checkout stash -- app.js

สิ่งนี้มีประโยชน์มากหากคุณกำลังทำงานในสองสาขาและไม่ต้องการกระทำ


13
หมายเหตุหนึ่ง: คุณจะได้รับสถานะล่าสุดของ app.js เท่านั้นคุณจะไม่ได้รับประวัติใด ๆ จากสาขาการทดสอบ
Frosty

2
@ThomasReggi คุณควรจะสามารถนำเข้า (ชำระเงิน) ไฟล์จากสาขาใด ๆ ไปยังสาขาปัจจุบันใด ๆ ถ้าคุณทำไม่ได้นั่นอาจเป็นคำถามที่ดีที่จะถามที่นี่พร้อมรายละเอียดเฉพาะเช่นข้อความแสดงข้อผิดพลาดที่แน่นอนและเวอร์ชันของ Git และ OS ที่ใช้
VonC

2
experiment:./app.jsในไดเรกทอรีย่อยนอกจากนี้คุณยังสามารถใช้ (คุณไม่ต้องระบุเส้นทางแบบเต็ม) ฉันได้เรียนรู้สิ่งนี้ขอบคุณข้อความแสดงข้อผิดพลาดที่มีประโยชน์มากที่ให้ฉัน: "คุณหมายถึง 'mybranch: full / path / to / my / file.xsl' aka 'mybranch: ./file.xsl '?" ใช่ฉันทำ! ฉันไม่คิดว่าฉันเคยดีใจมากกับข้อความแสดงข้อผิดพลาดร้ายแรง
Evan Lenz

1
@TomaszGandor ใช่ฉันพูดถึงว่าในstackoverflow.com/a/21066489/6309โดยที่การแสดง git จะไม่แก้ไขดัชนี แต่การชำระเงิน git จะปรับเปลี่ยนดัชนี
VonC

1
@FriedBrice ดูคำตอบของฉัน: วันนี้มันจะเป็นgit restore -s new-feature path/to/app.js
VonC

360

ทุกอย่างง่ายขึ้นมากใช้ git checkout สำหรับสิ่งนั้น

สมมติว่าyou're on masterสาขาเพื่อให้app.js from new-featureสาขาทำ:

git checkout new-feature path/to/app.js

// note that there is no leading slash in the path!

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

หมายเหตุ : new-featureต้องเป็นสาขาท้องถิ่นไม่ใช่สาขาระยะไกล


77
ฉันพบว่ามีประโยชน์ในการระบุที่มาเสมอgit checkout origin/source_branch path/to/fileเพราะหากคุณไม่ได้อัปเดตสาขาต้นทางของ repo ในพื้นที่ของคุณคุณอาจได้รับไฟล์เวอร์ชันเก่า ... ถามฉันว่าฉันรู้ได้อย่างไร ;)
talyric

3
@Mymozaaa คำถามไม่ได้พูดถึงรีโมทดังนั้นการสันนิษฐานว่ามันเป็น repo ท้องถิ่นอย่างหมดจด
Dmitry Avtonomov

1
คำสั่งนี้จะนำประวัติของไฟล์หรือไฟล์เวอร์ชั่นล่าสุดหรือไม่?
user1366265

1
@ user1366265 คำสั่งนี้จะทำให้ไฟล์เหมือนเดิมโดยเฉพาะการกระทำที่คุณระบุหรือหัวของสาขาที่คุณระบุ ไม่มีสิ่งเช่น "ประวัติของไฟล์" ข้อมูลประวัติทั้งหมดจะถูกเก็บไว้ในสาขาเท่านั้น
Dmitry Avtonomov

3
ดูเหมือนว่าจะจัดไฟล์ที่เช็คเอาต์โดยอัตโนมัติ มันเป็นไปได้ที่จะทำเช่นเดียวกันโดยไม่ต้องแสดงละคร?
bluenote10

44
git checkout branch_name file_name

ตัวอย่าง:

git checkout master App.java

สิ่งนี้จะไม่ทำงานหากชื่อสาขาของคุณมีระยะเวลา

git checkout "fix.june" alive.html
error: pathspec 'fix.june' did not match any file(s) known to git.

@PhilipRego คำตอบนี้ถูกต้อง ฉันเดาว่ามีตัวพิมพ์ใหญ่หรือเครื่องหมายวรรคตอนต่างกันในสาขาของคุณหรือคุณมีสาขาระยะไกลเท่านั้นไม่ใช่สาขาท้องถิ่น ดูเอกสารการชำระเงิน git: git-scm.com/docs/git-checkout#Documentation/ …
Bret

@ เบร่ฉันพบว่าใช้งานไม่ได้เมื่อชื่อสาขามีระยะเวลา ฉันแนะนำให้แก้ไข
Philip Rego

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

41

เพิ่มเติมจากคำตอบของ VonC และ chhh

git show experiment:path/to/relative/app.js > app.js
# If your current working directory is relative than just use
git show experiment:app.js > app.js

หรือ

git checkout experiment -- app.js

2
เย็น! ฉันเกลียดการระบุเส้นทางที่ยาว เครื่องหมายขีดกลางคู่ ( --) ระหว่างชื่อสาขาและเส้นทางเป็นตัวเลือกหรือไม่ มันเป็นเพียงเพื่อป้องกันเส้นทางซึ่งจะเริ่มต้นด้วยเส้นประจากการได้รับการปฏิบัติเป็นตัวเลือก / สวิทช์?
Tomasz Gandor

สุจริตฉันไม่รู้ ฉันไม่ได้สังเกตว่าฉันลืมเส้นประสองครั้งจนกว่าคุณจะชี้ให้เห็น
AlexLordThorsen

6
@TomaszGandor The --เป็นตัวเลือก แต่มีประโยชน์มากกว่าที่จะหลีกเลี่ยงข้อขัดแย้งกับชื่อสาขา ตัวอย่างเช่นgit checkout -- fooหมายถึง "ตรวจสอบไฟล์ foo จาก HEAD" (เช่นเขียนทับการเปลี่ยนแปลงในท้องถิ่นในfooเช่นชุดย่อยของgit reset --hard) แต่git checkout fooอาจหมายถึงว่าหรือ "ไปที่ branch foo "
Alois Mahdal

8

หรือถ้าคุณต้องการไฟล์ทั้งหมดจากสาขาอื่น:

git checkout <branch name> -- .

24
Queston เริ่มต้นประกอบด้วย "ไฟล์เดียว"
greatvovan

1
สิ่งนี้จะแทนที่ไฟล์ที่มีอยู่แทนที่จะทำการผสาน
Amare

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

4

ตรวจสอบไฟล์บน GitHub และดึงจากที่นั่น

นี่เป็นวิธีปฏิบัติที่ไม่ได้ตอบ OP โดยตรง แต่บางวิธีพบว่ามีประโยชน์:

หากสาขาที่มีปัญหานั้นอยู่บน GitHub คุณสามารถนำทางไปยังสาขาและไฟล์ที่ต้องการโดยใช้เครื่องมือมากมายที่ GitHub นำเสนอจากนั้นคลิก 'ดิบ' เพื่อดูข้อความธรรมดาและ (เลือก) คัดลอกและวางข้อความเป็น ต้องการ

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


2
อย่างไรก็ตามการคัดลอกและวางไฟล์ raw น่าจะทำให้เกิดการเปลี่ยนแปลงตัวละครที่ไม่ต้องการในคอมไพล์ของคุณ การบันทึกไฟล์ลงในโครงการของคุณโดยตรงนั้นปลอดภัยยิ่งขึ้นเพื่อให้แน่ใจว่าไม่มีการเปลี่ยนแปลง
ฟิลิป Rego

0

หากคุณต้องการไฟล์จากการกระทำที่เฉพาะเจาะจง (สาขาใด ๆ ) พูด 06f8251f

git checkout 06f8251f path_to_file

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

git checkout 06f8251f C: \ A \ B \ C \ D \ file.h


1
ขอบคุณที่สละเวลาตอบ! แต่นี่ไม่ได้ตอบคำถามและคำตอบที่ดีที่ detailled มากได้รับการโพสต์เมื่อ 9 ปีที่แล้ว ไม่จำเป็นต้องชนคำถาม
นาธาน

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

0

อีกวิธีหนึ่งคือการสร้างแพทช์ที่มีความแตกต่างและนำไปใช้ในสาขาหลักตัวอย่างเช่น สมมติว่าการส่งมอบครั้งสุดท้ายก่อนที่คุณจะเริ่มทำงานกับ app.js คือ 00000aaaaa และการส่งต่อเวอร์ชันที่คุณต้องการคือ 00000bbbbb

คุณเรียกใช้สิ่งนี้ในสาขาการทดสอบ:

git diff 00000aaaaa 00000bbbbb app.js > ~/app_changes.git

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

จากนั้นในต้นแบบคุณเพียงแค่เรียกใช้:

git apply ~/app_changes.git

ตอนนี้คุณจะเห็นการเปลี่ยนแปลงในโครงการราวกับว่าคุณทำมันด้วยตนเอง


-3
git checkout master               -go to the master branch first
git checkout <your-branch> -- <your-file> --copy your file data from your branch.

git show <your-branch>:path/to/<your-file> 

หวังว่านี่จะช่วยคุณได้ โปรดแจ้งให้เราทราบหากคุณมีข้อสงสัยใด ๆ

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