Як знайти видалений файл в історії фіксації проекту?


1274

Колись у моєму проекті був файл, який я зараз хотів би отримати.

Проблема полягає в тому, що я не маю уявлення про те, коли я його видалив і яким шляхом він був.

Як я можу знайти елементи цього файлу, коли він існував?


Схожий питання тут: stackoverflow.com/questions/7093602 / ...
Екес


13
Відповіді тут корисніші для мене, ніж відповіді у дублікатах .
Феліпе Альварес

5
погодився ... незалежно від дублікатів ... вони не з'явилися в пошуку Google .... цей зробив ... я сподіваюся, що ми перестанемо витрачати час на переслідування дублікатів ... тільки час і алгоритм Google скажіть, яке питання найкраще.
Тім Боланд

Відповіді:


1599

Якщо ви не знаєте точний шлях, який ви можете використовувати

git log --all --full-history -- "**/thefile.*"

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

git log --all --full-history -- <path-to-file>

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

git show <SHA> -- <path-to-file>

Або відновити його у робочій копії за допомогою:

git checkout <SHA>^ -- <path-to-file>

Зверніть увагу на символ caret ( ^), який отримує замовлення до ідентифікованого, оскільки в момент <SHA>фіксації файл видаляється, нам потрібно переглянути попередню комісію, щоб отримати вміст видаленого файлу


2
Спробуйте використовувати відносний шлях замість абсолютного (якщо ви ще цього не зробили).
Бурштин

63
Що робити, якщо ви не знаєте точного шляху? Все, що ви знаєте, це ім'я файлу?
священик

17
@PedroMorteRolo git log -- <path>не матиме результатів, коли ви знаходитесь на гілці, у якій файл ніколи не існував. Ви завжди повинні використовувати git log --all -- <path>, щоб переконатися, що ви не пропустите зміни, які відбулися на інших гілках. Команда git log -- <path>може бути дуже небезпечною, якщо у вас є кілька гілок і, як правило, забувають шляхи та гілки (як я), а також небезпечно, якщо ви працюєте з іншими розробниками.
варильні панелі

4
@ Amber, подумайте про те, щоб додати --all(дякую Філіпу ) свою git logвідповідь, щоб люди не пропускали змін та файлів на інших гілках. Це б врятувало забудькуючих людей, як я, багато горя.
варильні панелі

3
Як зазначено у відповіді нижче, відновлення файлу повинно бути git checkout <SHA>^ -- <path-to-file>(зверніть увагу на символ ^), тому що в момент <SHA> фіксації файл видаляється, нам потрібно переглянути попередню
комісію,

393

Отримайте список видалених файлів і скопіюйте повний шлях до видаленого файлу

git log --diff-filter=D --summary | grep delete

Виконайте наступну команду, щоб знайти ідентифікатор фіксації цього коміту та скопіюйте ідентифікатор фіксації

git log --all -- FILEPATH

Показати різницю видаленого файлу

git show COMMIT_ID -- FILE_PATH

Пам'ятайте, ви можете записати вихід у файл, використовуючи >подібні

git show COMMIT_ID -- FILE_PATH > deleted.diff

1
Хоча я знайшов шлях за допомогою першого кроку, другий крок видає цю помилку: unknown revision or path not in the working tree.
jvannistelrooy

6
Щоб побачити хеші фіксації разом з видаленими, ви можете зробитиgit log --diff-filter=D --summary | grep -E 'delete|^commit\s+\S+'
Кріс Міддлтон

1
Крок 2 нічого не повертає. Будь-які ідеї, чому це може статися? Ім'я мого файлу правильне.
Денис Княжев

2
Для того, щоб знайти поєднувати функції три в один, додайте це в .bashrc або .zshrc: git-grep-latest(){ result_path=$(git log --diff-filter=D --summary | grep $1 | head -1 | awk '{print $4;}'); latest_commit=$(git log --all -- $result_path | head -1 | awk '{print $2;}'); git show $latest_commit -- $result_path; }і тепер ви можете просто зробити:git-grep-latest some_text
randomor

1
@TylerJones ви можете подавати що завгодно що завгодно з Linux за допомогою труб - google linux pipes.. вам це сподобається.
Джон Хант

37

Не вдалося відредагувати прийняту відповідь, тому додавши її тут як відповідь,

щоб відновити файл у git, скористайтеся наступним (зверніть увагу на знак '^' відразу після SHA)

git checkout <SHA>^ -- /path/to/file

Я не розумію, чому ви хочете ^. Файл знаходиться в комісії з цим SHA ... чому ви хочете повернути ще один комітет звідти?
Тоні К.

19
Він укладається з цим ша "видаленим", що означає, що він досі не буде існувати. Ви повинні перейти до комісії перед цим, щоб фактично повернути його.
tandrewnichols

6
@tandrewnichols який просто означає , що ви використовуєте неправильний здійснює SHA - ви хочете, щоб зробити для версії файлу , який ви хочете ... , який , ймовірно , не варіант , коли файл буде видалений.
Бурштин

6
@ Бурштин і зобов'язання, яке ви хочете, є, ймовірно, останнім, перш ніж його було видалено, звідси і ця відповідь.
Сем Холдер

1
@AlexR: <SHA>~1має працювати так само, не потребуючи обгортання лапок.
CodeManX

37

Припустимо, ви хочете відновити названий файл MyFile, але не знаєте його шляху (або його розширення, з цього питання):

Prelim .: Уникайте плутанини, переходячи до кореня git

Нетривіальний проект може мати декілька каталогів з однаковими або однаковими назвами.

> cd <project-root>
  1. Знайдіть повний шлях

    git log --diff-filter = D - підсумок | grep видалити | grep MyFile

    delete mode 100644 full/path/to/MyFile.js

full/path/to/MyFile.js це шлях та файл, який ви шукаєте.

  1. Визначте всі коміти, які вплинули на цей файл

    git log --oneline - наступний - повний / шлях / до / MyFile.js

    bd8374c Some helpful commit message

    ba8d20e Another prior commit message affecting that file

    cfea812 The first message for a commit in which that file appeared.

  2. Оформити файл

Якщо ви вибрали перше перелічене фіксацію (останнє хронологічно, тут bd8374c), файл не буде знайдено, оскільки він був видалений у цій комісії.

> git checkout bd8374c -- full/path/to/MyFile.js

`error: pathspec 'full/path/to/MyFile.js' did not match any file(s) known to git.`

Просто виберіть попереднє (додайте каре) зобов'язання:

> git checkout bd8374c^ -- full/path/to/MyFile.js

3
Це набагато чіткіше, ніж прийнята відповідь
Поуян Ходабахш

для консолі Windows (cmd), використовуйте find замість grep на кроці 2: git log --diff-filter=D --summary | find "delete" | find "MyFile"І step3, зверніть увагу на лапки навколо хеша:git checkout "bd8374c^" -- full/path/to/MyFile.js
user5542121

30

@Amber дала правильну відповідь! Ще одне доповнення, якщо ви не знаєте точний шлях до файлу, ви можете використовувати символи! Це працювало для мене.

git log --all -- **/thefile.*

4
@PedroMorteRolo Хм. Я не знаю, як мені здається скопіювати існуючу відповідь у голосовані: / Ця відповідь була корисна і сама по собі; може бути достатньо виплат?
Clément

1
Цей файл не знаходить, якщо він знаходиться в корені проекту (перевірено в Cygwin).
wortwart

19

Нижче проста команда, де користувач або git може передати видалене ім’я файлу з кореневого каталогу сховища та отримати історію:

git log --diff-filter=D --summary | grep filename | awk '{print $4; exit}' | xargs git log --all -- 

Якщо хтось, може вдосконалити команду, будь ласка.


1
Дивовижне, дякую! Схоже, мого файлу взагалі ніколи не існувало, але це окрема проблема, яка суттєво переживає…

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

Спасибі @samaspin оновив відповідь.
Джейсон

18

Спробуйте скористатись одним із глядачів, наприклад gitkтаким, щоб ви могли переглядати історію, щоб знайти половину запам’ятованого файлу. (використовувати gitk --allза потреби для всіх відділень)


4
Цей --allваріант є критичним як для вашої відповіді, так і для прийнятої відповіді.
варильні панелі

3
Перегляд історії займе надзвичайно багато часу для більшості проектів.
mikemaccana

5

Підсумок:

  1. Крок 1

Ви шукаєте повний шлях до файлу в історії видалених файлів git log --diff-filter=D --summary | grep filename

  1. Крок 2

Ви відновите свій файл з комісії перед його видаленням

restore () {
  filepath="$@"
  last_commit=$(git log --all --full-history -- $filepath | grep commit | head -1 | awk '{print $2; exit}')
  echo "Restoring file from commit before $last_commit"
  git checkout $last_commit^ -- $filepath
}

restore my/file_path

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