Найти, когда файл был удален в Git
У меня есть репозиторий Git с n коммитами.
У меня есть файл, который мне нужен, и который раньше был в репозитории, и что я вдруг ищу и думаю: "О, где этот файл?"
Есть ли (серия) команды Git, которые скажут мне, что "file really_needed.txt был удален при фиксации n-13"?
Другими словами, не глядя на каждую отдельную фиксацию и зная, что у моего репозитория Git есть все изменения каждого файла, могу ли я быстро найти последний коммит, который имеет этот файл, чтобы я мог его вернуть?
Ответы
Ответ 1
git log --full-history -- [file path]
показывает изменения файла, работают, даже если файл был удален.
Пример:
git log --full-history -- myfile
Если вы хотите видеть только последний коммит, который удалил файл, используйте дополнительно -1, например, git log --full-history -1 -- [file path]
См. Какой коммит удалил файл
Ответ 2
Краткий ответ:
git log --full-history -- your_file
покажет вам все коммиты в вашей истории репо, включая коммиты слияния, которые касались your_file
. Последний (верхний) - тот, который удалил файл.
Некоторое объяснение:
Флаг --full-history
здесь важен. Без этого Git выполняет "упрощение истории", когда вы запрашиваете лог файла. В документах подробно рассказывается о том, как именно это работает, и мне не хватает храбрости и смелости, необходимых для того, чтобы попытаться выяснить это из исходного кода, но в документации git-log есть, что сказать:
Режим по умолчанию
Упрощает историю до самой простой истории, объясняющей конечное состояние дерева. Проще всего, потому что он отбрасывает некоторые боковые ветки, если конечный результат один и тот же (то есть объединение ветвей с одинаковым содержимым)
Это, очевидно, относится к случаю, когда файл, история которого мы хотим, удаляется, поскольку самой простой историей, объясняющей конечное состояние удаленного файла, не является история. Есть ли риск, что git log
без --full-history
просто заявит, что файл никогда не создавался? К сожалению, да. Вот демонстрация:
[email protected]:~/example$ git init
Initialised empty Git repository in /home/mark/example/.git/
[email protected]:~/example$ touch foo && git add foo && git commit -m "Added foo"
[master (root-commit) ddff7a7] Added foo
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 foo
[email protected]:~/example$ git checkout -b newbranch
Switched to a new branch 'newbranch'
[email protected]:~/example$ touch bar && git add bar && git commit -m "Added bar"
[newbranch 7f9299a] Added bar
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 bar
[email protected]:~/example$ git checkout master
Switched to branch 'master'
[email protected]:~/example$ git rm foo && git commit -m "Deleted foo"
rm 'foo'
[master 7740344] Deleted foo
1 file changed, 0 insertions(+), 0 deletions(-)
delete mode 100644 foo
[email protected]:~/example$ git checkout newbranch
Switched to branch 'newbranch'
[email protected]:~/example$ git rm bar && git commit -m "Deleted bar"
rm 'bar'
[newbranch 873ed35] Deleted bar
1 file changed, 0 insertions(+), 0 deletions(-)
delete mode 100644 bar
[email protected]:~/example$ git checkout master
Switched to branch 'master'
[email protected]:~/example$ git merge newbranch
Already up-to-date!
Merge made by the 'recursive' strategy.
[email protected]:~/example$ git log -- foo
commit 77403443a13a93073289f95a782307b1ebc21162
Author: Mark Amery
Date: Tue Jan 12 22:50:50 2016 +0000
Deleted foo
commit ddff7a78068aefb7a4d19c82e718099cf57be694
Author: Mark Amery
Date: Tue Jan 12 22:50:19 2016 +0000
Added foo
[email protected]:~/example$ git log -- bar
[email protected]:~/example$ git log --full-history -- foo
commit 2463e56a21e8ee529a59b63f2c6fcc9914a2b37c
Merge: 7740344 873ed35
Author: Mark Amery
Date: Tue Jan 12 22:51:36 2016 +0000
Merge branch 'newbranch'
commit 77403443a13a93073289f95a782307b1ebc21162
Author: Mark Amery
Date: Tue Jan 12 22:50:50 2016 +0000
Deleted foo
commit ddff7a78068aefb7a4d19c82e718099cf57be694
Author: Mark Amery
Date: Tue Jan 12 22:50:19 2016 +0000
Added foo
[email protected]:~/example$ git log --full-history -- bar
commit 873ed352c5e0f296b26d1582b3b0b2d99e40d37c
Author: Mark Amery
Date: Tue Jan 12 22:51:29 2016 +0000
Deleted bar
commit 7f9299a80cc9114bf9f415e1e9a849f5d02f94ec
Author: Mark Amery
Date: Tue Jan 12 22:50:38 2016 +0000
Added bar
Обратите внимание, что git log -- bar
в приведенном выше дампе терминала приводит к буквальному отсутствию вывода; Git "упрощает" историю до вымысла, где bar
никогда не существовало. git log --full-history -- bar
, с другой стороны, дает нам коммит, который создал bar
и коммит, который его удалил.
Чтобы было ясно: этот вопрос не просто теоретический. Я только просмотрел документы и обнаружил флаг --full-history
, потому что git log -- some_file
не удался для меня в реальном хранилище, где я пытался отследить удаленный файл. Упрощение истории иногда может быть полезно, когда вы пытаетесь понять, как существующий в данный момент файл оказался в его текущем состоянии, но при попытке отследить удаление файла он с большей вероятностью испортит вас, скрыв коммит, который вас волнует, Всегда используйте флаг --full-history
для этого варианта использования.
Ответ 3
Git, но вам нужно префикс пути с помощью --
Например:
dan-mac:test dani$ git log file1.txt
fatal: ambiguous argument 'file1.txt': unknown revision or path not in the working tree.
dan-mac:test dani$ git log -- file1.txt
commit 0f7c4e1c36e0b39225d10b26f3dea40ad128b976
Author: Daniel Palacio <[email protected]>
Date: Tue Jul 26 23:32:20 2011 -0500
foo
Ответ 4
Я только что добавил решение здесь (есть ли способ в git перечислить все удаленные файлы в репозитории?) для обнаружения коммитов удаленных файлов с помощью regexp:
git log --diff-filter=D --summary | sed -n '/^commit/h;/\/some_dir\//{G;s/\ncommit \(.*\)/ \1/gp}'
Это возвращает все удаленные в каталоге с именем some_dir
(каскадирование). Любое sed regexp там, где \/some_dir\/
будет делать.
OSX (благодаря @triplee и @keif)
git log --diff-filter=D --summary | sed -n -e '/^commit/h' -e '\:/:{' -e G -e 's/\ncommit \(.*\)/ \1/gp' -e }
Ответ 5
Вы можете найти последний коммит, который удалил файл, следующим образом:
git rev-list -n 1 HEAD -- [file_path]
Дополнительная информация доступна здесь
Ответ 6
Это работает для меня на OSX:
git log --diff-filter=D --summary | sed -n -e '/^commit/h' -e '\:/:{' -e G -e 's/\ncommit \(.*\)/ \1/gp' -e ‘}