ฉันจะแตกไฟล์เดียวกันระหว่างสองคอมมิตที่ต่างกันในสาขาเดียวกันได้อย่างไร?


1143

ใน Git ฉันจะเปรียบเทียบไฟล์เดียวกันระหว่างสองคอมมิทที่ต่างกัน (ไม่ต่อเนื่องกัน) ในสาขาเดียวกันได้อย่างไร (ตัวอย่างเช่นมาสเตอร์)

ฉันกำลังค้นหาคุณสมบัติการเปรียบเทียบเช่นเดียวกับในVisual SourceSafe (VSS) หรือTeam Foundation Server (TFS)
เป็นไปได้ใน Git?

คำตอบ:


1475

จากgit-diffmanpage:

git diff [--options] <commit> <commit> [--] [<path>...]

ตัวอย่างเช่นหากต้องการดูความแตกต่างของไฟล์ "main.c" ระหว่างนี้ถึงสองคอมมิตย้อนกลับนี่คือคำสั่งที่เทียบเท่ากันสามคำ:

$ git diff HEAD^^ HEAD main.c
$ git diff HEAD^^..HEAD -- main.c
$ git diff HEAD~2 HEAD -- main.c

43
..ไม่จำเป็นจริงๆแม้ว่ามันจะทำงานกับมัน (ยกเว้นในรุ่นเก่าเป็นธรรมอาจจะ) นอกจากนี้คุณยังสามารถใช้git logหรือgitkค้นหา SHA1 ที่จะใช้หากการกระทำทั้งสองอยู่ห่างกันมาก gitkนอกจากนี้ยังมี "diff select -> this" และ "diff this -> selected" ในเมนูบริบท
Cascabel

17
มันจะใช้งานได้แม้ว่าชื่อไฟล์จะถูกแก้ไขระหว่าง 2 คอมมิทหรือไม่?
reubenjohn

26
ดังนั้นวัตถุประสงค์ของ "-"
อะไร

29
@ user64141 เป็นเช่นประโยชน์เมื่อคุณมีไฟล์ชื่อ-- -pเหมาะสำหรับใช้ในสคริปต์เฉพาะในบางกรณีที่จำเป็นต้องใช้ในทางปฏิบัติ
Palec

13
หมายเหตุ: คุณต้องใช้พา ธ ที่สัมพันธ์กับรูทของธุรกรรมซื้อคืน พา ธ ที่สัมพันธ์กับไดเร็กทอรีการทำงานปัจจุบันจะไม่ทำงาน
Kevin Wheeler

280

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

git diff <revision_1>:<file_1> <revision_2>:<file_2>


25
ทราบว่าดูเหมือนว่าถ้า<file_1>และ<file_2>อยู่ในไดเรกทอรีปัจจุบันไม่ได้อยู่ในไดเรกทอรีคอมไพล์ระดับบนสุดที่มีการจัดการที่หนึ่งที่มีการย่อหน้า./บน Unix:<revision_1>:./filename_1
อังเดร Holzner

7
<revision>: สามารถลบล้างได้ดังนั้นคุณสามารถแตกต่างกับไฟล์ที่ยังไม่ได้คอมมิท
Yaroslav Nikitenko

2
โปรดทราบว่าใน Windows หนึ่งต้องใช้ '/' สำหรับเส้นทางของไฟล์ไม่ใช่ '\'
np8

87

หากคุณได้กำหนดค่า "difftool" คุณสามารถใช้

git difftool revision_1:file_1 revision_2:file_2

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

$git difftool HEAD:src/main/java/com.xyz.test/MyApp.java HEAD^:src/main/java/com.xyz.test/MyApp.java

คุณควรมีรายการต่อไปนี้ใน ~ / .gitconfig ของคุณหรือในไฟล์ project / .git / config ติดตั้ง p4merge [นี่คือเครื่องมือ diff และผสานที่ฉันต้องการ]

[merge]
    tool = p4merge
    keepBackup = false
[diff]
    tool = p4merge
    keepBackup = false
[difftool "p4merge"]
    path = C:/Program Files (x86)/Perforce/p4merge.exe
[mergetool]
    keepBackup = false
[difftool]
    keepBackup = false
[mergetool "p4merge"]
    path = C:/Program Files (x86)/Perforce/p4merge.exe
    cmd = p4merge.exe \"$BASE\" \"$LOCAL\" \"$REMOTE\" \"$MERGED\"

50

ตรวจสอบ$ git logคัดลอกรหัสSHA-1ของทั้งสองคอมมิทที่ต่างกันและรันgit diffคำสั่งด้วย ID เหล่านั้น ตัวอย่างเช่น:

$ git diff (sha-id-one) (sha-id-two)

18
หากคุณต้องการ diff สำหรับไฟล์เฉพาะให้เพิ่มพา ธ ไปที่ท้ายคำสั่ง
hBrent

นอกจากนี้ยังทำ "git pull" เพื่อดาวน์โหลดข้อมูลต้นไม้เต็มรูปแบบหากการกระทำทั้งสองข้ามสาขาที่ต่างกัน มิฉะนั้นคุณจะได้รับข้อผิดพลาด "ร้ายแรง: วัตถุที่ไม่ดี"
user238607

4
git diff (sha-id-one) (sha-id-two) -- filename.ext โดยไม่มีชื่อไฟล์มันจะแสดงรายการที่แตกต่างของไฟล์ทั้งหมดในทั้งสองกระทำ
SherylHohman

40

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

git log -u $start_commit..$end_commit -- path/to/file


"$ start_commit" และ "$ end_commit" คืออะไร พวกเขาเป็นตัวอักษรหรือไม่ถ้าคุณสามารถให้ตัวอย่าง?
Peter Mortensen

เหล่านี้คือตัวแปรของเชลล์ที่มีการแก้ไขเริ่มต้นและสิ้นสุดซึ่งสามารถเป็น sha1 literals หรือ refs ได้
cxreg

21

นี่คือสคริปต์ Perl ที่พิมพ์คำสั่ง Git diff สำหรับไฟล์ที่กำหนดตามที่พบในคำสั่ง Git log

เช่น

git log pom.xml | perl gldiff.pl 3 pom.xml

อัตราผลตอบแทน:

git diff 5cc287:pom.xml e8e420:pom.xml
git diff 3aa914:pom.xml 7476e1:pom.xml
git diff 422bfd:pom.xml f92ad8:pom.xml

/bin/shซึ่งก็อาจจะมีการตัดและวางในเซสชั่นหน้าต่างเปลือกหรือประปา

หมายเหตุ:

  1. หมายเลข (3 ในกรณีนี้) ระบุจำนวนบรรทัดที่จะพิมพ์
  2. ไฟล์ (pom.xml ในกรณีนี้) จะต้องตกลงกันในทั้งสองแห่ง (คุณสามารถใส่ไว้ในฟังก์ชั่นเชลล์เพื่อให้ไฟล์เดียวกันในทั้งสองที่) หรือวางไว้ในไดเรกทอรีไบนารีเป็นสคริปต์เชลล์

รหัส:

# gldiff.pl
use strict;

my $max  = shift;
my $file = shift;

die "not a number" unless $max =~ m/\d+/;
die "not a file"   unless -f $file;

my $count;
my @lines;

while (<>) {
    chomp;
    next unless s/^commit\s+(.*)//;
    my $commit = $1;
    push @lines, sprintf "%s:%s", substr($commit,0,6),$file;
    if (@lines == 2) {
        printf "git diff %s %s\n", @lines;
        @lines = ();
    }
    last if ++$count >= $max *2;
}

14

หากคุณต้องการสร้างไฟล์ที่มีมากกว่าหนึ่งไฟล์โดยใช้วิธีการที่ระบุโดย @mipadi:

เช่นความแตกต่างระหว่างHEADและของคุณmasterเพื่อค้นหา.coffeeไฟล์ทั้งหมด:

git diff master..HEAD -- `find your_search_folder/ -name '*.coffee'`

วิธีนี้จะค้นหาไฟล์your_search_folder/ทั้งหมดของคุณซ้ำ.coffeeและสร้างความแตกต่างระหว่างไฟล์เหล่านั้นกับmasterเวอร์ชัน


13

หากคุณมีหลายไฟล์หรือไดเรกทอรีและต้องการเปรียบเทียบการกระทำที่ไม่ต่อเนื่องคุณสามารถทำได้:

ทำให้สาขาชั่วคราว ( "แก้ไข"ในตัวอย่างนี้)

git checkout -b revision

ย้อนกลับไปยังเป้าหมายการส่งมอบครั้งแรก

git reset --hard <commit_target>

เชอร์รี่เลือกผู้ที่สนใจ

git cherry-pick <commit_interested> ...

ใช้ diff

git diff <commit-target>^

เมื่อเสร็จแล้ว

git branch -D revision

2
ขอบคุณสำหรับการแก้ปัญหานี้ มันทำงานได้ดีสำหรับกรณีการใช้งานของฉัน สิ่งเดียวที่ฉันจะอัปเดตก็คือเมื่อคุณทำคุณไม่สามารถลบสาขาได้จนกว่าคุณจะปิดมัน
Steven Dix

9

อีกวิธีหนึ่งในการใช้ความสุดยอดของ Git ...

git difftool HEAD HEAD@{N} /PATH/FILE.ext

ฉันกำหนดนามแฝงจากคำตอบนี้ที่ใช้ได้กับ bash:difftool-file = "!git difftool HEAD@{\"$2\"} HEAD \"$1\" #"
blueogive

2

หากคุณต้องการเปรียบเทียบภาพอย่างง่าย ๆ บน Windows เช่นคุณสามารถรับในVisual SourceSafeหรือTeam Foundation Server (TFS) ลองสิ่งนี้

  • คลิกขวาที่ไฟล์ใน File Explorer
  • เลือก 'ประวัติ Git'

หมายเหตุ: หลังจากอัปเกรดเป็น Windows 10 ฉันทำตัวเลือกเมนูบริบทของ Git หายไป อย่างไรก็ตามคุณสามารถทำสิ่งเดียวกันโดยใช้ 'gitk' หรือ 'gitk filename' ในหน้าต่างคำสั่ง

เมื่อคุณเรียก 'Git History' เครื่องมือ Git GUI จะเริ่มต้นโดยมีประวัติของไฟล์ในบานหน้าต่างซ้ายบน เลือกหนึ่งในรุ่นที่คุณต้องการเปรียบเทียบ จากนั้นคลิกขวาที่รุ่นที่สองและเลือกอย่างใดอย่างหนึ่ง

กระจายสิ่งนี้ -> เลือกไว้

หรือ

เลือกที่แตกต่าง -> สิ่งนี้

ความแตกต่างของรหัสสีจะปรากฏในบานหน้าต่างด้านซ้ายล่าง


หมายเหตุสำหรับ downvoters: นี่เป็นโซลูชันที่ง่ายใช้งานง่ายและแก้ไขปัญหาของ OP มันทำงานบน Windows ที่ OP ใช้อย่างชัดเจน (ดูการอ้างอิงถึง TFS และ VSS ในคำถาม)
ทรัพยากร
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.