Як зробити git diff для переміщеного / перейменованого файлу?


128

Я перемістив файл за допомогою git mv. Тепер я хотів би зробити відмінності для нового файлу, щоб порівняти його зі старим файлом (зі старим, неіснуючим іменем).

Як це зробити?


4
Незабаром (git 2.9, червень 2016) git diff -- yourRenamedFileбуде достатньо простого . Дивіться мою відповідь нижче
VonC

Відповіді:


145

Вам потрібно використовувати -M, щоб дозволити git автоматично виявляти переміщений файл при різництві. Використовувати так само, git diffяк згадуваний трикотаж, для мене не працює.

Так просто: 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
Рятувальник! Мій git відмінний зараз набагато кращий. 1) Чи безпечно завжди використовувати цей варіант? 2) Чи можу я додати цю опцію як поведінку за замовчуванням до своєї ~/.gitconfig?
kevinarpe

5
Зверніть увагу, що виявлення перейменування працює лише тоді, коли і старі, і нові файли з'являються в колекції файлів, оброблених git diff. Запуск git diff -Mу одному (перейменованому) файлі не повідомляє про перейменування.
Леон

1
Це не працює для мене, але git log --follow -- file_after_move.txtпрацює добре. Він показує всю історію, в тому числі перед переїздом. Будь-які ідеї? Я бігаю git version 2.11.0.windows.1.
Був'єр

1
-CВаріант для виявлення копій є корисним і подібним. Я використовував це -Mдля розгляду різниці, де я відновив один файл на два (при цьому жодне ім'я не відповідає оригіналу).
cp.engr

85

Окрім того, що написав трикотаж , ви завжди можете використовувати:

git diff HEAD:./oldfilename newfilename

де HEAD:./oldfilenameозначає старе ім'я файлу в останньому коміті (в HEAD), відносно поточного каталогу.

Якщо у вас немає достатньо нового git, вам доведеться використовувати замість цього:

git diff HEAD:path/to/oldfilename newfilename

8
Дякую за це Ви також можете вказати конкретний комітет замість голови, тобтоgit diff 39fa7c77e85c51d43ea0cf30d33aec8721812e9e:./oldfilename newfilename
Кріс Блум

8
Якщо це незрозуміло, ви також можете вказати назви філій чи будь-яку іншу посилання, наприклад:git diff branch:old/filen.name newfilename
jricher

Перша форма працює для мене, якщо ви cdв каталог і не додаєте --перед commit:pathпарою. Git, здається, дуже вибагливий із синтаксисом.
безтурботний

1
@dhardy <commit-ish>:<pathname>Синтаксис - це ідентифікатор об'єкта, щось Git-ish; після того, як --Git очікує лише імена файлів.
Якуб Нарбський

18

З git 2.9 (червень 2016 року) вам більше не доведеться додавати -M. git diffвикористовує -Mза замовчуванням.

Див. Команду 5404c11 , фіксування 9501d19 , фіксування a9276a6 , фіксування f07fc9e , здійснення 62df1e6 (25 лютого 2016 р.) Матьє Моя ( moy) .
(Об’єднав Хуніо С Хамано - gitster- у комітеті 5d2a30d , 03 квітня 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

git config diff.renamelimit 450

і перезапустіть свою команду diff.


0

З будь-якої причини використання HEAD:./oldfilename(або абсолютний шлях) не працювало для мене, але все- HEAD:oldfilenameтаки (спасибі cmn):

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

HTH


Можливо, ваш git занадто старий, щоб зрозуміти HEAD:./oldfilename?
Якуб Нарбський

-4

просто запустіть git diffбез жодних аргументів, або git diff -- newfilename. git досить розумний для порівняння потрібних файлів / вмісту (тобто оригінальний вміст перед перейменуванням та змінений вміст після перейменування)


2
git абсолютно не досить розумний у більшості випадків. Якщо просто git mvвикористати один файл, а потім порівнювати поетапний стан з іншою ідентичною гілкою, ви отримаєте різницю, "якщо все було видалено та відтворено заново", якщо тільки не -Mбуде використано.
Reinderien
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.