git ต่างเปลี่ยนชื่อไฟล์


105

a.txtฉันมีไฟล์

cat a.txt
> hello

เนื้อหาa.txtคือ "สวัสดี"

ฉันทำสัญญา

git add a.txt
git commit -m "first commit"

ฉันก็ย้ายa.txtไปเป็นtestผบ.

mkdir test
mv a.txt test

จากนั้นฉันก็ทำการคอมมิตครั้งที่สอง

git add -A
git commit -m "second commit"

สุดท้ายฉันแก้ไขa.txtเป็น "ลาก่อน" แทน

cat a.txt
> goodbye

ฉันทำสิ่งสุดท้ายของฉัน

git add a.txt
git commit -m "final commit"

นี่คือคำถามของฉัน:

ฉันจะทำให้เนื้อหาa.txtระหว่างคอมมิตล่าสุดกับคอมมิตแรกแตกต่างกันอย่างไร

ฉันได้ลองแล้ว: git diff HEAD^^..HEAD -M a.txtแต่ไม่ได้ผล git log --follow a.txtตรวจพบการเปลี่ยนชื่ออย่างถูกต้อง แต่ฉันไม่พบสิ่งที่เทียบเท่าสำหรับgit diff. มีหรือเปล่า


ฉันคิดว่ามันจะเหมือนกันถ้าคุณทำ 'git mv a.txt test'? IE คุณเพิ่งเปลี่ยนชื่อไฟล์แทนที่จะย้ายไปไว้ในไดเรกทอรีย่อย
Max Waterman

คำตอบ:


107

ปัญหาเกี่ยวกับความแตกต่างระหว่างHEAD^^และHEADคือคุณมีการa.txtกระทำทั้งสองดังนั้นเมื่อพิจารณาจากการกระทำทั้งสอง (ซึ่งแตกต่างกันอย่างไร) ไม่มีการเปลี่ยนชื่อมีสำเนาและการเปลี่ยนแปลง

ในการตรวจหาสำเนาคุณสามารถใช้-C:

git diff -C HEAD^^ HEAD

ผลลัพธ์:

index ce01362..dd7e1c6 100644
--- a/a.txt
+++ b/a.txt
@@ -1 +1 @@
-hello
+goodbye
diff --git a/a.txt b/test/a.txt
similarity index 100%
copy from a.txt
copy to test/a.txt

อนึ่งหากคุณ จำกัด ความแตกต่างของคุณไว้เพียงเส้นทางเดียว (เช่นเดียวกับที่คุณทำgit diff HEAD^^ HEAD a.txtคุณจะไม่เห็นการเปลี่ยนชื่อหรือสำเนาเนื่องจากคุณได้แยกทุกอย่างออกจากเส้นทางเดียวและการเปลี่ยนชื่อหรือสำเนา - ตามคำจำกัดความเกี่ยวข้องกับสองเส้นทาง เส้นทาง


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

3
@KenHirakawa ใช้-- <old-path> <new-path>... ดูคำตอบของฉัน
Nolan Amy

ในกรณีของฉันฉันต้องการแสดงรายละเอียดของการคอมมิตที่ไฟล์ถูกเปลี่ยนชื่อ แต่มันแสดงให้ฉันเห็นว่าไฟล์ถูกลบและมีการเพิ่มไฟล์ ... ฉันรันgit show -C [commit]และมันจำได้ว่าไฟล์นั้นเปลี่ยนชื่อและแสดงให้ฉันเห็น แตกต่างระหว่างไฟล์ สมบูรณ์แบบ.
Jason

83

หากต้องการเปลี่ยนชื่อไฟล์ที่แตกต่างกันให้ใช้-M -- <old-path> <new-path>( ใช้-Cงานได้เช่นกัน)

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

git diff HEAD^ HEAD -M -- a.txt test/a.txt

สิ่งนี้ก่อให้เกิด:

diff --git a/a.txt b/test/a.txt
similarity index 55%
rename from a.txt
rename to test/a.txt
index 3f855b5..949dd15 100644
--- a/a.txt
+++ b/test/a.txt
@@ -1,3 +1,3 @@
 // a.txt

-hello
+goodbye

( // a.txtเพิ่มบรรทัดเพื่อช่วยในการตรวจจับการเปลี่ยนชื่อ)


หาก git ตรวจไม่พบการเปลี่ยนชื่อคุณสามารถระบุเกณฑ์ความคล้ายคลึงกันต่ำโดย-M[=n]พูด 1%:

git diff HEAD^ HEAD -M01 -- a.txt test/a.txt

จากเอกสาร git diff :

-M [<n>] - ค้นหาเปลี่ยนชื่อ [= <n>]

ตรวจจับการเปลี่ยนชื่อ หากnระบุไว้จะเป็นเกณฑ์ของดัชนีความคล้ายคลึงกัน (เช่นจำนวนการเพิ่ม / ลบเมื่อเทียบกับขนาดของไฟล์) ตัวอย่างเช่น-M90%หมายความว่า Git ควรพิจารณาคู่ลบ / เพิ่มเพื่อเปลี่ยนชื่อหากไฟล์มากกว่า 90% ไม่มีการเปลี่ยนแปลง หากไม่มี%เครื่องหมายจะต้องอ่านตัวเลขเป็นเศษส่วนโดยมีจุดทศนิยมอยู่ข้างหน้า กล่าวคือ-M5จะกลายเป็น 0.5 -M50%และดังนั้นจึงเป็นเช่นเดียวกับ ในทำนองเดียวกันเป็นเช่นเดียวกับ-M05 -M5%เพื่อ จำกัด -M100%การตรวจสอบการเปลี่ยนชื่อที่แน่นอนการใช้งาน ดัชนีความคล้ายคลึงเริ่มต้นคือ 50%


... แน่นอนว่ายังใช้งานได้เมื่อการเปลี่ยนแปลงและการเปลี่ยนชื่ออยู่ในการกระทำที่แยกจากกันดังตัวอย่างเดิม:git diff HEAD^^ HEAD -M -- a.txt test/a.txt
Nolan Amy

1
เฉพาะเมื่อเนื้อหาของไฟล์อยู่ใกล้พอที่จะทำให้ diff สร้างดัชนีความคล้ายคลึงกันได้ การใช้ทั้งสองตัวเลือก (-M และ -C) แสดงความแตกต่างเป็น / dev / null จาก / dev / null ในไฟล์ที่ถูกเปลี่ยนชื่อและมีการเปลี่ยนแปลงทั้งหมด (รวมถึงการเยื้องที่ชาญฉลาด) ซึ่งจะไม่จับได้เมื่อละเว้น ช่องว่าง
DavidG

37

คุณยังสามารถทำ:

git diff rev1:file1 rev2:file2

ซึ่งสำหรับตัวอย่างของคุณจะเป็น

git diff HEAD^^:./a.txt HEAD:./test/a.txt

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

สิ่งนี้ไม่ได้ขึ้นอยู่กับการตรวจจับการเปลี่ยนชื่อเลยเนื่องจากผู้ใช้ระบุอย่างชัดเจนว่าจะเปรียบเทียบอะไร (ดังนั้นจึงมีประโยชน์ในบางสถานการณ์เช่นการเปรียบเทียบไฟล์ระหว่างสาขา svn ที่แตกต่างกันในสภาพแวดล้อม git-svn)


1
ดีจังเลย!
Nolan Amy

สำหรับการเปลี่ยนชื่อด้วยการเปลี่ยนแปลงไฟล์เพิ่มเติมที่นำมาจากการผสานนี่เป็นคำตอบเดียวที่เหมาะกับฉัน ขอบคุณ!
Lane Rettig

1

หากการเปลี่ยนชื่อคอมมิตของคุณถูกจัดฉาก แต่ยังไม่ได้คอมมิตคุณสามารถใช้:

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