Як знайти останню версію git, яка змінила файл?


180

Я хочу знайти останню версію, яка змінила вихідний файл.

Я можу використовувати, git blameщоб побачити всі дати комісій по кожному рядку, але важко зрозуміти, яка саме фіксація була останньою, яка торкнулася файлу.

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

Відповіді:


230

git log підтримує перегляд історії конкретних файлів (та каталогів), тому ви можете назвати це так:

git log my/file.c

Якщо ви дійсно хочете тільки перерахувати один останній Комміт, наприклад , щоб використовувати його в сценарії, використовуйте -n 1опцію:

git log -n 1 --pretty=format:%H -- my/file.c

--pretty=format:%hповідомляє git logпоказувати лише хеш фіксації. --Separater зупиняє ім'я файлу від того , щоб інтерпретувати як Комміт ім'я, тільки в разі , якщо це неоднозначно.


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

44

Якщо ви просто хочете знайти найновішу комісію, ви не хочете git-log, ви хочете git-rev-list, в якій перераховуються об'єкти фіксації, що змінюють цей файл, в цьому шляху передачі, починаючи з останнього (хронологічно). Простіше кажучи:

git rev-list -1 <commit> <filename>

Бо git-rev-listу вашому випадку ви просто постачаєте:

  • Кількість комісій, які потрібно включити, або -1 лише для останніх,
  • Гілка (або ввести ідентифікатор), щоб почати оглядатися назад, HEAD, якщо ви вже на ній, або --all, якщо ви хочете, щоб усі відомі комісії, і
  • Відносний шлях до вашого файлу.

Це просто повертає останній ідентифікатор комісії в поточній гілці для зміни цього файлу, наприклад: 215095e2e338525be0baeeebdf66bfbb304e7270

Для більш складного прикладу ви можете використовувати імена тегів та навіть віддалені посилання та включати відносні імена шляхів із символами підстановки, наприклад:

git rev-list origin/user/bob/testbranch -1 src/bfiles/*.txt

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

Звичайно, зверніться до git-rev-list (1) Сторінка посібника .


Ви дійсно не пояснили, чому використання git-logне поступається.
Пьотр Доброгост

7
Я б не сказав, що вона неповноцінна, лише те, що вона надає сторонні відомості за замовчуванням. git-rev-list просто повертає ідентифікатор фіксації, який ви хочете, якщо ви збираєтеся подати відповідь у сценарій чи інший процес автоматизації. git-log повертає інформацію про вибрані комісії, спочатку використовуючи git-rev-list для збору ідентифікаторів комісій, а потім збираючи інформацію про кожну комісію. Якщо ви просто збираєтеся відфільтрувати інформацію про фіксацію та використовувати ідентифікатори, то ви можете просто використовувати git-rev-list в першу чергу. Оскільки журнал заснований на списку rev-списку, він приймає більшість однакових параметрів фільтра.
Майкл Еріксон

3
git-logє порцеляновим, git-rev-listсантехнічним.
blitzen9872

27

Якщо ви хочете просто отримати хеш останньої версії для зміни певного набору файлів (і хочете уникати awk), ви можете використовувати:

git log -n 1 --pretty=format:%h -- <path>

Це може бути корисно для отримання хеш-файлів для подальшого використання git describe .

Наприклад (якщо це корисно для когось) ...

Я створюю поточний ідентифікатор версії, враховуючи останню прихильність змінити будь-який вихідний файл (припускаючи, що ви позначите версії такими тегами mycode-1.2.1):

COMMIT=$(git log -n 1 --pretty=format:%h -- *.c *.h)
if VN=$(git describe --always --abbrev=5 --match "mycode-*" $COMMIT 2>/dev/null) &&
case "$VN" in
mycode-*)
    git update-index -q --refresh
    test -z "$(git diff-index --name-only HEAD *.c *.h)" ||
    VN="$VN-mod" ;;
*) VN="mycode-unknown-g$VN" ;;
esac
then
    continue
else
VN="mycode-unknown"
fi

Це створює ідентифікатори, наприклад:

  • mycode-1.2.1 - коли поточний стан вихідних файлів відповідає тегованій версії
  • mycode-1.2.1-g3k7s2 - коли поточний стан вихідних файлів відповідає виконувати наступні теги версії
  • mycode-1.2.1-g3k7s2-mod - коли поточний стан вихідних файлів було змінено з моменту останнього фіксації після тегованої версії
  • mycode-unknown - коли ще не створено тег версії

5
$VNвиглядає як якийсь кошмар нежиті SVN
ThorSummoner

10

Я не впевнений, що це те, що ви хочете, але якщо ви зробите, git log <thefile>щоб отримати коміти, які змінили цей файл. Можна вибрати верхній. Це має бути той, кого ви шукаєте.


4
якщо ви використовуєте git log -n1 -- <thefile>(або направити висновок , head -1якщо ви хочете , щоб витрачати ресурси) , ви не повинні вручну вибрати верхню лінію (див Джо Лісс відповіді )
Тобіас Kienzler

4
Гарна думка. Я думаю, ви також можете пропустити -nта використовувати -1безпосередньо.
Нуфал Ібрагім


2

Коли у вас є ідентифікатор SHA комісії, який ви хочете переглянути git log FILENAME, ви повинні мати змогу зробити, git show SHA_ID_HEREщоб побачити, що ви зробили для конкретного вчинення. Вам навіть не потрібно вводити весь ідентифікатор; перших 6 символів має бути достатньо.


4
це трохи більше, ніж просили ОП, але FYI ви можете об'єднати це в git show $(git log -1 --pretty="%H" -- FILENAME)
однолінійний
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.