Найти, когда файл был удален в Git

У меня есть репозиторий Git с N коммитами.

У меня есть файл, который мне нужен, и который раньше был в репозитории, и который я вдруг ищу и думаю: "о! Куда делась эта папка?"

есть ли (серия) команд Git, которые скажут мне ,что " файл really_needed.txt был удален при фиксации n-13"?

другими словами, не глядя на каждую отдельную фиксацию и зная, что мое git repo имеет каждое изменение каждого файла, я могу быстро найти последний зафиксировать, что есть этот файл, чтобы я мог его вернуть?

4 ответов


git log -- [file path] показывает тенденцию изменения файла, даже если файл был удален.

git log -1 -- [file path]

посмотреть который commit удалил файл


короткий ответ:

git log --full-history -- your_file

покажет все коммиты в истории вашего РЕПО, включая коммиты слияния, которые коснулись your_file. Последний (верхний) - это тот, который удалил файл.

объяснение:

на --full-history флаг здесь важен. Без него Git выполняет "упрощение истории", когда вы просите его для журнала файла. Документы освещают детали о том, как именно это работает, и мне не хватает смелости и мужества требуется попробовать и выяснить это из исходного кода, но документы git-log есть что сказать:

режим по умолчанию

упрощает историю до простейшей истории, объясняющей конечное состояние дерева. Простейший, потому что он обрезает некоторые боковые ветви, если конечный результат тот же (т. е. слияние ветвей с тем же содержимым)

это, очевидно, касается, когда файл, история которого мы хотим удалены, так как самая простая история, объясняющая конечное состояние удаленного файла, -нет истории. Есть ли риск, что git log без --full-history будет просто утверждать, что файл никогда не был создан? К сожалению, да. Вот пример:

mark@lunchbox:~/example$ git init
Initialised empty Git repository in /home/mark/example/.git/
mark@lunchbox:~/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
mark@lunchbox:~/example$ git checkout -b newbranch
Switched to a new branch 'newbranch'
mark@lunchbox:~/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
mark@lunchbox:~/example$ git checkout master
Switched to branch 'master'
mark@lunchbox:~/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
mark@lunchbox:~/example$ git checkout newbranch
Switched to branch 'newbranch'
mark@lunchbox:~/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
mark@lunchbox:~/example$ git checkout master
Switched to branch 'master'
mark@lunchbox:~/example$ git merge newbranch
Already up-to-date!
Merge made by the 'recursive' strategy.
mark@lunchbox:~/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
mark@lunchbox:~/example$ git log -- bar
mark@lunchbox:~/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
mark@lunchbox:~/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 флаг для этого дела использовать.


git log, но вам нужно префикс пути с --

например:

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 <danpal@gmail.com>
 Date:   Tue Jul 26 23:32:20 2011 -0500

 foo

Я только что добавил решение здесь (есть ли способ в git перечислить все удаленные файлы в репозитории?) для поиска коммитов удаленных файлов с помощью regexp:

git log --diff-filter=D --summary | sed -n '/^commit/h;/\/some_dir\//{G;s/\ncommit \(.*\)/ /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 \(.*\)/ /gp' -e }