จะทำอย่างไรให้ git แตกต่างกับไฟล์ที่ย้าย / เปลี่ยนชื่อ?


128

ฉันย้ายไฟล์โดยใช้git mv. ตอนนี้ฉันต้องการสร้างความแตกต่างในไฟล์ใหม่เพื่อเปรียบเทียบกับไฟล์เก่า (ด้วยชื่อเก่าตอนนี้ไม่มีอยู่จริง)

ฉันต้องทำอย่างไร


4
เร็ว ๆ นี้ (git 2.9, มิถุนายน 2016) ง่ายๆgit diff -- yourRenamedFileก็เพียงพอแล้ว ดูคำตอบของฉันด้านล่าง
VonC

คำตอบ:


145

คุณต้องใช้ -M เพื่อให้ git ตรวจหาไฟล์ที่ย้ายโดยอัตโนมัติเมื่อแตกต่างกัน การใช้git diffknittl ที่กล่าวถึงไม่ได้ผลสำหรับฉัน

เพียงแค่: git diff -Mควรทำ

เอกสารสำหรับสวิตช์นี้คือ:

-M[<n>], --find-renames[=<n>]
       Detect renames. If n is specified, it is a threshold on the similarity index 
       (i.e. amount of addition/deletions compared to the file’s size). For example, 
       -M90% means git should consider a delete/add pair to be a rename if more than
       90% of the file hasn’t changed.

7
ช่วยชีวิต! ความแตกต่างของคอมไพล์ของฉันดีขึ้นมากแล้ว 1) ปลอดภัยไหมที่จะใช้ตัวเลือกนี้ 2) ฉันสามารถเพิ่มตัวเลือกนี้เป็นพฤติกรรมเริ่มต้นของฉันได้~/.gitconfigหรือไม่?
kevinarpe

5
หมายเหตุ: git diffการตรวจสอบการเปลี่ยนชื่อที่ใช้งานได้เฉพาะเมื่อทั้งสองไฟล์เก่าและใหม่ปรากฏในคอลเลกชันของไฟล์ที่ประมวลผลโดย การเรียกใช้git diff -Mไฟล์เดียว (เปลี่ยนชื่อ) จะไม่รายงานการเปลี่ยนชื่อ
Leon

1
สิ่งนี้ไม่ได้ผลสำหรับฉัน แต่ git log --follow -- file_after_move.txtใช้ได้ผลดี จะแสดงประวัติทั้งหมดรวมทั้งก่อนการย้าย ความคิดใด ๆ ? git version 2.11.0.windows.1ฉันกำลังทำงาน
bouvierr

1
-Cตัวเลือกสำหรับการตรวจสอบสำเนาเป็นประโยชน์และที่คล้ายกัน ฉันใช้กับ-Mเพื่อดูความแตกต่างที่ฉันได้ refactored หนึ่งไฟล์เป็นสองไฟล์ (โดยที่ชื่อไม่ตรงกับต้นฉบับ)
cp.engr

85

นอกจากสิ่งที่knittl เขียนแล้วคุณยังสามารถใช้:

git diff HEAD:./oldfilename newfilename

โดยที่HEAD:./oldfilenameหมายถึง oldfilename ในการกระทำสุดท้าย (ใน HEAD) สัมพันธ์กับไดเร็กทอรีปัจจุบัน

หากคุณไม่มีคอมไพล์ใหม่เพียงพอคุณจะต้องใช้แทน:

git diff HEAD:path/to/oldfilename newfilename

8
ขอบคุณสำหรับสิ่งนี้. นอกจากนี้คุณยังสามารถระบุการกระทำที่เฉพาะเจาะจงแทนส่วนหัวได้เช่นgit diff 39fa7c77e85c51d43ea0cf30d33aec8721812e9e:./oldfilename newfilename
Chris Bloom

8
ในกรณีที่ไม่ชัดเจนคุณสามารถระบุชื่อสาขาหรือข้อมูลอ้างอิงอื่น ๆ ได้เช่นgit diff branch:old/filen.name newfilename
jricher

แบบฟอร์มแรกใช้ได้กับฉันถ้าคุณcdไปที่ไดเร็กทอรีและไม่ต้องเพิ่ม--ก่อนcommit:pathคู่ Git ดูเหมือนจะจู้จี้จุกจิกมากกับไวยากรณ์ที่นี่
dhardy

1
@dhardy <commit-ish>:<pathname>ไวยากรณ์คือตัวระบุวัตถุบางอย่าง Git-ish; หลังจาก--Git ต้องการชื่อไฟล์เท่านั้น
Jakub Narębski

18

ด้วย git 2.9 (มิถุนายน 2016) คุณจะไม่ต้องเพิ่ม-Mอีกต่อไป git diffใช้-Mโดยค่าเริ่มต้น

ดูกระทำ 5404c11 , กระทำ 9501d19 , กระทำ a9276a6 , กระทำ f07fc9e , กระทำ 62df1e6 (25 กุมภาพันธ์ 2016) โดยMatthieu Moy (moy )
(รวมโดยJunio C Hamano - gitster-ในการกระทำ 5d2a30d , 3 เมษายน 2016)

diff: เปิดใช้งานdiff.renamesตามค่าเริ่มต้น

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

การคัดค้านที่อาจเกิดขึ้นในการเปิดใช้งานการตรวจจับการเปลี่ยนชื่อคือบางครั้งอาจล้มเหลวและบางครั้งก็ช้า แต่การตรวจจับการเปลี่ยนชื่อจะเปิดใช้งานโดยค่าเริ่มต้นแล้วในหลายกรณีเช่น " git status" และ " git merge" ดังนั้นการเปิดใช้งานจึงdiff.renamesไม่ได้เปลี่ยนสถานการณ์โดยพื้นฐาน เมื่อการตรวจจับการเปลี่ยนชื่อล้มเหลวตอนนี้จะล้มเหลวอย่างต่อเนื่องระหว่าง " git diff" และ " git status"

การตั้งค่านี้ไม่มีผลต่อคำสั่งเกี่ยวกับระบบประปาดังนั้นสคริปต์ที่เขียนอย่างดีจะไม่ได้รับผลกระทบ

การทดสอบใหม่สำหรับคุณลักษณะนี้อยู่ที่นี่


1

git diff -Mเปิดใช้งานการตรวจจับการเปลี่ยนชื่อตามที่คนอื่นพูด (และตามที่ @VonC ชี้ให้เห็นจะเปิดใช้งานตามค่าเริ่มต้นจาก git 2.9) แต่ถ้าคุณมีชุดการเปลี่ยนแปลงขนาดใหญ่การตรวจจับการเปลี่ยนชื่อที่ไม่แน่นอนอาจยังคงถูกปิดอีกครั้ง Git จะแสดงคำเตือนดังต่อไปนี้ซึ่งง่ายต่อการพลาดท่ามกลางความแตกต่างที่คุณกำลังรับชม:

warning: inexact rename detection was skipped due to too many files.
warning: you may want to set your diff.renameLimit variable to at least 450 and retry the command.

ในกรณีนั้นให้ตั้งค่าตัวเลือกการกำหนดค่าตามที่คอมไพล์แนะนำเช่น

git config diff.renamelimit 450

และรันคำสั่ง diff ของคุณอีกครั้ง


0

ไม่ว่าด้วยเหตุผลใดก็ตามการใช้HEAD:./oldfilename(หรือเส้นทางสัมบูรณ์) ไม่ได้ผลสำหรับฉัน แต่HEAD:oldfilenameทำ (ขอบคุณ cmn):

git diff HEAD:oldfilename newfilename
git diff 2a80f45:oldfilename f65f3b3:newfilename

HTH


บางทีคอมไพล์ของคุณเก่าเกินไปที่จะเข้าใจHEAD:./oldfilename?
Jakub Narębski

-4

เพียงแค่เรียกใช้git diffโดยไม่มีข้อโต้แย้งใด ๆ หรือgit diff -- newfilename. git ฉลาดพอที่จะเปรียบเทียบไฟล์ / เนื้อหาที่เหมาะสม (เช่นเนื้อหาต้นฉบับก่อนเปลี่ยนชื่อด้วยเนื้อหาที่เปลี่ยนแปลงหลังจากเปลี่ยนชื่อ)


2
git ไม่ฉลาดพอในกรณีส่วนใหญ่ เพียงแค่ติดgit mvตั้งไฟล์เดียวแล้วเปรียบเทียบสถานะการจัดฉากกับสาขาอื่นที่เหมือนกันจะทำให้เกิดความแตกต่าง "ทุกอย่างถูกลบและสร้างขึ้นใหม่อีกครั้ง" เว้นแต่-Mจะใช้
Reinderien
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.