Як РЕАЛЬНО показати журнали перейменованих файлів із git?


132

Я відносно новачка в git, раніше я використовувала Subversion.

Я помітив, що більшість графічних git-фронтальних та IDE-плагінів, здається, не можуть відобразити історію файлу, якщо файл був перейменований. Коли я користуюся

git log --follow

у командному рядку я можу побачити весь журнал у перейменах.

За словами Лінуса Торвальдса, перемикач --фоллоу - це плеєр "SVN noob", серйозні користувачі git не користуються ним:

--follow - це тотальний хак, призначений просто задовольнити колишніх користувачів SVN, які ніколи нічого не знали про такі речі, як батьківство чи гарні графіки перегляду.

Це не зовсім фундаментально, але нинішня реалізація "- наступного" - це дійсно швидка попередня обробка, яка зафіксована на логіці переходу до редагування, а не в тому, що є щось дійсно цілісне.

Буквально він був розроблений як плісера "SVN noob", а не як "справжня функціональність git". Ідея полягала в тому, що ви відволічетеся від (зламаного) мислення, яке перейменовує матерію у великій картині.

Моє запитання : Як користувачі хардкор-git серед вас отримують історію файлу, коли він перейменований? Який "реальний" спосіб це зробити?


17
@David Hall: git mv oldfile newfileне викликає перейменування повинні бути записані на всіх - це точно так же , як видалення одного файлу і додавання іншого. git працює лише перейменовує та копіює стан дерева при кожному введенні після факту.
Марк Лонгейр

20
@David Hall: Якщо ви перейменовуєте файл за допомогою іншого інструменту за межами git (наприклад, /bin/mv oldfile newfile), але потім робите git add newfile; git rm oldfile, результат не відрізняється від цього git mv oldfile newfile.
Марк Лонгейр

1
Ця ідеологія розпадається, якщо ви коли-небудь перемістите файл до нового сховища, і в цьому випадку неможливість перемістити всю його історію може бути головною проблемою. Хоча, звичайно, є обмеження щодо того, наскільки справді може скластися справжня історія з файлом у складному проекті.
Роман Старков

1
Примітка: git log --followтрохи покращується git 2.9 (червень 2016): дивіться мою відповідь нижче
VonC

1
Станом на v2.15, ви можете поекспериментувати з --color-movedвами diff.
Майкл

Відповіді:


71

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

Перейменування файлу - це невеликий особливий випадок "вмісту", що рухається між шляхами. У вас може бути функція, яка переміщується між файлами, які користувач git може функціонально відстежувати за допомогою "pickaxe" (наприклад,log -S ).

Інші зміни "шляху" включають комбінування та розділення файлів; git не дуже важливо, який файл ви вважаєте перейменованим, а який ви вважаєте скопійованим (або перейменованим та видаленим), він просто відстежує повний вміст вашого дерева.

git заохочує "ціле дерево" думати, де стільки систем управління версіями дуже орієнтовані на файли. Ось чому git частіше посилається на "стежки", ніж на "назви файлів".


Привіт Чарльз, дякую за вашу відповідь. Здається, я використовую git так само, як і SVN. Хоча я розумію, що git дуже відрізняється від інших систем контролю версій, але багато понять в git мені ще здаються дивними ... Я, мабуть, повинен закінчити цю книгу git, яку я нещодавно купив.
Майк

24
Точка Лінуса полягала в тому, що "належний" gui зможе відслідковувати фрагменти коду через файли, і він сподівався, що до цього часу у нас будуть такі інструменти. На жаль, у нас все ще немає такої розкоші, і - наступне все ще корисно.
Майкл Паркер

11
Чи справді git дає вам інше рішення, ніж --followце?
Griwes

13
Я б заперечував, що мислення на «ціле дерево» посилюється за --followзамовчуванням. Що я маю на увазі, коли я хочу бачити історію коду у файлі, мені дійсно все одно, чи перейменований файл чи ні, я просто хочу переглянути історію коду, незалежно від перейменовань. Тому, на мою думку, це має сенс --followбути типовим, бо я не переймаюся окремими файлами; --followдопомагає мені ігнорувати окремі перейменування файлів, які, як правило, є неістотними.
Відредаговано

2
Отже ... якщо я вирішив подбати про "вміст" замість файлу, як я надрукую комісії, що стосуються вмісту, який зараз знаходиться у цьому файлі? Я був би радий, якби git відстежував це в різних файлах для мене і повідомляв про журнал усіх змін - я просто не бачу, як його отримати.
Ed Avis

36

У мене точно таке саме питання, з яким ви стикаєтесь. Незважаючи на те, що я не можу дати вам відповіді, я вважаю, що ви можете прочитати цей електронний лист, який Лінус написав ще в 2005 році, він дуже доречний і може дати вам підказку щодо вирішення проблеми:

… Я стверджую, що будь-яка СКМ, яка намагається відстежувати перейменування, принципово порушена, якщо це не робиться з внутрішніх причин (тобто для дозволу ефективних дельт), саме тому, що перейменування не мають значення. Вони вам не допомагають, і все одно не те, що вас цікавило .

Важливим є пошук «звідки це взялося», а архітектура git справді робить це дуже добре - набагато краще, ніж все інше там. …

Я знайшов посилання на це повідомлення в блозі, що також може бути корисним для вас, щоб знайти життєздатне рішення:

У повідомленні Лінус окреслив, як ідеальна система відстеження контенту може дозволити вам знайти, як блок коду увійшов у поточну форму. Ви б почали з поточного блоку коду у файлі, поверніться в історію, щоб знайти комісію, яка змінила файл. Потім ви перевіряєте зміну комітету, щоб побачити, чи цікавий вам блок коду змінений ним, оскільки фіксація, яка змінює файл, може не торкатися блоку коду, який вас цікавить, а лише деяких інших частин файл.

Коли ви виявите, що до фіксації код коду не існував у файлі, ви перевіряєте фіксацію глибше. Ви можете виявити, що це одна з багатьох можливих ситуацій, зокрема:

  1. Комітет справді ввів блок коду. Автор комітету був винахідником тієї класної функції, на яку ви полювали (або винна сторона, яка ввела помилку); або
  2. Блок коду у файлі не існував, але п'ять однакових його копій існували в різних файлах, всі вони зникли після фіксації. Автор фіксує повторно налаштований дубльований код, ввівши єдину помічну функцію; або
  3. (як особливий випадок) До фіксації файл, який наразі містить цікавий для вас код коду, не існував, але існував ще один файл з майже однаковим вмістом, і блок коду, який вас цікавить, разом з усім іншим вмістом у файлі тоді існував у тому іншому файлі. Це пішло після вчинення. Автор комітету перейменував файл, надавши йому незначну модифікацію.

У git, остаточний інструмент відстеження контенту Лінуса ще не існує повністю автоматизованим способом. Але більшість важливих інгредієнтів уже доступні.

Будь ласка, повідомте нас про ваш прогрес у цьому.


Дякуємо за публікацію цих статей. Тільки до того, як я прочитав їх, я повністю зрозумів ідею історії контенту! Я думав про це не так!
DavidG

Цей електронний лист від Лінуса чудовий, дякую за публікацію цього повідомлення.
mik01aj

Цікаво, що Git v2.15 додає--color-moved рух до цієї "ідеальної системи стеження". Я грав з ним, щоб побачити, як він відслідковує переміщені рядки у файлі, але випадково зрозумів, що він відслідковує переміщені рядки у всій розл.
Майкл

2
Лінус пояснює складну ситуацію. Але тут у нас проста ситуація: файл просто перейменований (або переміщений в інший каталог). Таким чином, повинно бути просте рішення. Я думаю, що проблема виходить із того, що суперечить Subversion, користувач не може доручити Git під час фіксації, звідки походить файл, і це --followможе бути помилково (наприклад, якщо два файли мають однаковий вміст або якщо є модифікація крім переміщення файлу).
vinc17

13

Я помітив, що більшість графічних git передніх версій та плагінів IDE, здається, не можуть відобразити історію файлу, якщо файл був перейменований

Ви будете раді дізнатися, що деякі популярні інструменти Git UI зараз це підтримують. Є кілька десятків інструментів користувальницького інтерфейсу Git, тому я не перелічу їх усіх, але, наприклад:

  • Під час перегляду журналу файлів SourceTree має внизу ліворуч прапорець "Дотримуватися перейменованих файлів"
  • У вікні журналу внизу зліва у TortoiseGit встановлено прапорець "слідкувати за перейменами".

Детальніше про інструменти Git UI:


Джерело чудово працює при перейменуванні один раз, при перейменуванні двічі, зміни даних не доступні для комітетів перед перейменуванням. Я повідомив про помилку тут: jira.atlassian.com/browse/SRCTREE-5715
Intel

gitk чудово працює, навіть коли файл перейменований двічі за всю історію. Команда виглядає приблизно так: "gitk - наступний шлях / до / файл"
Intel

6

Примітка: git 2.9 (червень 2016 р.) Значно покращить "баггічний" характер git log --follow:

Див. Комісію ca4e3ca (30 березня 2016 р.) Від SZEDER Gábor ( szeder) .
(Об'єднав Хуніо С Хамано - gitster- у комітеті 26effb8 , 13 квітня 2016 р.)

diffcore: фіксуйте порядок ітерації однакових файлів під час виявлення перейменування

Якщо два шляхи ' dir/A/file' і ' dir/B/file' мають однаковий вміст і батьківський каталог перейменовано, наприклад, ' git mv dir other-dir', то diffcoreповідомляються про наступні точні перейменування:

renamed:    dir/B/file -> other-dir/A/file
renamed:    dir/A/file -> other-dir/B/file

(зверніть увагу на інверсію тут: B/file -> A/fileі A/file -> B/file)

Хоча технічно це не так, це заплутає не тільки користувача, але й команди git, які приймають рішення на основі інформації про перейменування, наприклад ' git log --follow other-dir/A/file' слідує ''dir/B/file за перейменом.

Така поведінка є побічним ефектом фиксации v2.0.0-rc4 ~ 8 ^ 2 ~ 14 ( diffcore-rename.c: спростити пошук точних перейменовань, 2013-11-14): хешмап, що зберігає джерела, повертає записи з того ж відра, тобто джерела, що відповідають поточному призначенню , у порядку LIFO.
Таким чином, ітерація спочатку вивчає ' other-dir/A/file' і ' dir/B/file' і, знаходячи однаковий зміст та базову назву, повідомляє точне перейменування.


2

У Linux я переконався, що SmartGit та GitEye здатні слідувати за перейменами під час перегляду історії певного файлу. Однак, на відміну від gitk та GitEye, SmartGit показує окремий вигляд файлу та перегляд сховища (який містить структуру каталогу, але не список файлів, що містяться в ньому)

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