วิธีการเปรียบเทียบไฟล์จากสองสาขาที่แตกต่างกันอย่างไร


1537

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

เพื่อความชัดเจนฉันไม่ได้กำลังมองหาเครื่องมือเปรียบเทียบ (ฉันใช้ Beyond Compare) ฉันกำลังมองหาคำสั่ง git diff ที่จะให้ฉันเปรียบเทียบรุ่นต้นแบบกับรุ่นสาขาปัจจุบันของฉันเพื่อดูว่ามีการเปลี่ยนแปลงอย่างไร ฉันไม่ได้อยู่ระหว่างการรวมหรืออะไรก็ตาม ฉันแค่อยากจะพูดอะไรบางอย่างเช่น

git diff mybranch/myfile.cs master/myfile.cs

คำตอบ:


2208

git diff สามารถแสดงความแตกต่างระหว่างสองคอมมิท:

git diff mybranch master -- myfile.cs

หรือเทียบเท่า:

git diff mybranch..master -- myfile.cs

ใช้ไวยากรณ์หลังถ้าด้านใดด้านหนึ่งHEADมันอาจจะถูกละเว้น (เช่นmaster..เปรียบเทียบmasterกับHEAD)

คุณอาจสนใจmybranch...master(จากgit diffเอกสาร ):

แบบฟอร์มนี้เพื่อดูการเปลี่ยนแปลงในสาขาที่มีถึงสองเริ่มต้นที่มีบรรพบุรุษร่วมกันของทั้งสอง<commit> เทียบเท่ากับ<commit>git diff A...Bgit diff $(git-merge-base A B) B

กล่าวอีกนัยหนึ่งสิ่งนี้จะให้ความแตกต่างของการเปลี่ยนแปลงmasterนับตั้งแต่ถูกแยกออกจากmybranch(แต่ไม่มีการเปลี่ยนแปลงใหม่ตั้งแต่นั้นมาmybranch)


ในทุกกรณี--ตัวคั่นหน้าชื่อไฟล์บ่งบอกถึงจุดสิ้นสุดของแฟล็กบรรทัดคำสั่ง ตัวเลือกนี้เป็นทางเลือกเว้นแต่ Git จะสับสนหากการอ้างถึงการคอมมิชชันหรือไฟล์ แต่การรวมกันนั้นไม่ใช่นิสัยที่ไม่ดี ดูhttps://stackoverflow.com/a/13321491/54249สำหรับตัวอย่าง


สามารถส่งผ่านอาร์กิวเมนต์เดียวกันไปที่git difftoolถ้าคุณมีการกำหนดค่าอย่างใดอย่างหนึ่ง


44
git diff branch1 branch2 myfile.csและถ้าทั้งสองรุ่นที่คุณต้องการเปรียบเทียบเป็นต้นไม้ที่ทำงานคุณสามารถใช้ ( --ไม่จำเป็นอีกต่อไปเนื่องจากสามารถใช้การโต้แย้งการแก้ไขได้ถึงสองครั้งเท่านั้น)
Cascabel

8
ฉันลองทุกรุ่นแล้วไม่มีอะไรเกิดขึ้น ฉันกำหนดค่า difftool ของฉันแล้ว (ใช้ได้สำหรับการรวม) ฉันมีไฟล์ชื่อ bd.ps1 ทุกรุ่นของคำสั่งที่ฉันพิมพ์ไม่ทำอะไรเลย ไม่แม้แต่จะทำผิดพลาด WTH!?!?!
คา

3
@Micah: คุณลองด้วยความแตกต่างธรรมดาด้วยหรือเปล่า? คุณพิมพ์เส้นทางที่สัมพันธ์กับไดเรกทอรีปัจจุบันอย่างถูกต้องหรือไม่ (ไฟล์นี้จะไม่แสดงที่ต่างไปจากเดิมอย่างเงียบ ๆ หากไม่มีไฟล์อยู่และคุณใช้--ข้อผิดพลาดทั่วไปและใช้งานง่ายที่จะทำ)
Cascabel

5
สิ่งนี้ไม่ได้ผลสำหรับฉันจนกว่าฉันจะรวมเส้นทางแบบเต็มไปยังไฟล์ดังที่แสดงโดยgit diff --name-status branch1..branch2(อาจชัดเจน แต่คิดว่าฉันจะพูดถึงมันในกรณีที่คนอื่นมีปัญหาแบบเดียวกันกับที่ฉันทำ)
hBrent

4
ลำดับของ mybranch และมาสเตอร์ก็สำคัญเช่นกัน ไฟล์ในสาขาแรกจะแสดงด้วยคำนำหน้า '-' ไฟล์ในสาขาที่สองจะแสดงด้วยคำนำหน้า '+'
timbo

414

คุณสามารถทำได้: git diff branch1:path/to/file branch2:path/to/file

หากคุณกำหนดค่า difftool แล้วคุณยังสามารถ: git difftool branch1:path/to/file branch2:path/to/file

คำถามที่เกี่ยวข้อง: ฉันจะดูเอาต์พุต git diff ด้วยโปรแกรม diff diff ได้อย่างไร


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

13
@Jefromi นี่อาจมีการเปลี่ยนแปลงในรุ่นที่ใหม่กว่า แต่อย่างน้อยตอนนี้คุณสามารถใช้เส้นทางสัมพัทธ์ (เช่นbranch1:./file) นอกจากนี้ยังมีประโยชน์หากไฟล์อยู่ในตำแหน่งแยกระหว่างสาขา (เช่นgit diff branch1:old/path/to/file branch2:new/path/to/file)
redbmk

4
@redbmk ใช่นั่นเป็นช่วงเวลาระหว่างปี 2010 ถึงตอนนี้! ถึงกระนั้นถ้ามันเป็นไฟล์เดียวกันทั้งสองสาขาไม่จำเป็นต้องทำอย่างนี้git diff branch1 branch2 path/to/fileเลย
Cascabel

3
@jefromi ยอดเยี่ยมฉันไม่แน่ใจว่าไทม์ไลน์จะเปิดเมื่อใด ใช่ปกติฉันจะใช้ไวยากรณ์ที่คุณพูดถึง แต่คำตอบของ Tim ช่วยให้ฉันหาวิธีเปรียบเทียบไฟล์กับพา ธ ที่แตกต่างกันถึงแม้ว่ามันจะไม่ใช่คำถามที่ถาม
จริงๆ

1
ในขณะที่ฉันรักความคิดนี้ฉันไม่สามารถรับไวยากรณ์นี้เพื่อทำงานหรือค้นหาการอ้างถึงในเอกสาร diff git ฉันพลาดอะไรไป ขอบคุณ!
yoyo

160

ไวยากรณ์ที่ทันสมัยมากขึ้น:

git diff ..master path/to/file

คำนำหน้าสองจุดหมายถึง "จากไดเรกทอรีทำงานปัจจุบันถึง" คุณสามารถพูดได้ว่า:

  • master..คือการย้อนกลับของด้านบน masterนี้เป็นเช่นเดียวกับ
  • mybranch..masterอ้างอิงอย่างชัดเจนถึงสถานะอื่นนอกเหนือจากแผนผังการทำงานปัจจุบัน
  • v2.0.1..masterเช่นการอ้างอิงแท็ก
  • [refspec]..[refspec]โดยทั่วไปสิ่งใดที่สามารถระบุได้ว่าเป็นสถานะของรหัสในคอมไพล์

33

มีหลายวิธีในการเปรียบเทียบไฟล์จากสองสาขาที่แตกต่างกัน:

  • ตัวเลือก 1:ถ้าคุณต้องการเปรียบเทียบไฟล์จาก n branch เฉพาะกับสาขาอื่น:

    git diff branch1name branch2name path/to/file
    

    ตัวอย่าง:

    git diff mybranch/myfile.cs mysecondbranch/myfile.cs
    

    ในตัวอย่างนี้คุณกำลังเปรียบเทียบไฟล์ในสาขา“ mybranch” กับไฟล์ในสาขา“ mysecondbranch”

  • ตัวเลือก 2:วิธีง่าย ๆ :

     git diff branch1:file branch2:file
    

    ตัวอย่าง:

     git diff mybranch:myfile.cs mysecondbranch:myfile.cs
    

    ตัวอย่างนี้คล้ายกับตัวเลือก 1

  • ตัวเลือก 3:ถ้าคุณต้องการเปรียบเทียบไดเรกทอรีการทำงานปัจจุบันของคุณกับบางสาขา:

    git diff ..someBranch path/to/file
    

    ตัวอย่าง:

    git diff ..master myfile.cs
    

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


12

ฉันแค่ทำ git diff branch1 branch2 path/to/file

การตรวจสอบความแตกต่างระหว่างไฟล์ การเปลี่ยนแปลงในbranch1จะเป็นสีแดง การเปลี่ยนแปลงในbranch2จะเป็นสีเขียว

สันนิษฐานว่าbranch1เป็นอดีตและbranch2เป็นอนาคต คุณสามารถกลับรายการนี้ได้โดยกลับลำดับของสาขาในส่วนต่าง:git diff branch2 branch1


Git รุ่นใดที่สามารถทำสิ่งนี้ได้? ดูเหมือนจะไม่ได้รับการสนับสนุนในรุ่นที่ฉันใช้งานอยู่ (2..9.2.windows.1)
วินซ์ Bowdren

9

หากคุณต้องการสร้างความแตกต่างจากสาขาปัจจุบันคุณสามารถใช้มันและใช้:

git diff $BRANCH -- path/to/file

วิธีนี้จะแตกต่างจากสาขาปัจจุบันไปยังสาขาอ้างอิง ( $BRANCH)


5

เห็นด้วยกับคำตอบที่แนะนำโดย @dahlbyk หากคุณต้องการให้ diff ถูกเขียนไปยังไฟล์ diff สำหรับการตรวจทานโค้ดให้ใช้คำสั่งต่อไปนี้

git diff branch master -- filepath/filename.extension > filename.diff --cached

2

ในกรณีของฉันฉันใช้คำสั่งด้านล่าง:

git diff <branch name> -- <path + file name>

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


1

วิธีที่ดีที่สุดที่จะทำคือการใช้git diffวิธีต่อไปนี้: git diff <source_branch> <target_branch> -- file_path

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


1

ใช้แฮชการกระทำเช่นนี้:

git diff <hash1> <hash2> <filename>

ที่HASH1สามารถใดกระทำจากสาขาใด ๆ เหมือนกันสำหรับhash2


1

มีสองสถานการณ์ที่จะเปรียบเทียบไฟล์:

สถานการณ์ที่ 1:เปรียบเทียบไฟล์ที่สาขาระยะไกล (ทั้งสองสาขาควรมีอยู่ในที่เก็บระยะไกล)

สถานการณ์จำลอง 2:เปรียบเทียบไฟล์โลคัล (ที่สำเนาพื้นที่ทำงานโลคัล) กับไฟล์ที่ที่เก็บรีโมต

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

เช่นชำระเงินที่สาขา

git checkout branch1
git diff branch2 [filename]

ในกรณีนี้หากคุณระบุชื่อไฟล์มันจะเปรียบเทียบสำเนาชื่อไฟล์ในเครื่องของคุณกับสาขาระยะไกลชื่อ " branch2 "

git diff branch1 branch2 [filename]

ในกรณีนี้มันจะเปรียบเทียบชื่อไฟล์จากสาขาระยะไกลชื่อ " branch1 " กับ " branch2 "

git diff ..branch2 [filename]

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

หวังว่ามันจะมีประโยชน์


0

ในการเปรียบเทียบสองไฟล์ใน bash git คุณต้องใช้คำสั่ง:

git diff <Branch name>..master -- Filename.extension   

คำสั่งนี้จะแสดงความแตกต่างระหว่างสองไฟล์ใน bash เอง

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