Git: знайти видалений код


76

Це робить мене горіхом.

Як знайти код, який було видалено?

Я в підсумку виявив, де це було створено з цим:

$ git log --pretty=oneline -S'some code'

І це досить добре, але мені також було цікаво дізнатись, де воно було видалено, і поки що, без кісток.

Спочатку я намагався git diff HEAD..HEAD^|grep 'some code', щоразу розширюючи діапазон, поки не знайшов рядки, де його було видалено. Приємно, тому припустимо, що я знайшов його в діапазоні HEAD^^..HEAD^^^, тоді я роблю git show HEAD^^^і git show HEAD^^з grep, але коду ніде не знайти!

Потім я читаю трохи далі git bisect, і, звичайно, це дає мені єдину версію, де повинен бути винуватець ... Знову, git show rev|grep 'some code'виходить порожнім ...

Що за? Що я роблю не так?

Дякую!


2
Ви хочете сказати, що коли ви виконуєте в основному наступне, ви не отримуєте жодних звернень ?: <pre> SHAHIT = `git log --pretty = oneline -S'some code '| голова -1 | awk '{print $ 1}' 'git show $ SHAHIT | grep 'деякий код' </pre> Якщо так, здається нечутливим .... якщо він є log, він повинен бути видимим у show... так? А може, я неправильно розумію питання.
metasim

Минув якийсь час, коли я опинився в цій ситуації, і вона більше не представлялася, тому я не можу перевірити вашу команду. Все одно спасибі, це може комусь стати в нагоді.
Іван

1
Стара публікація / коментар тут, але саме те, що мені все-таки потрібно. @SimeonFitch ваш синтаксис відмінно спрацював для мене, щоб знайти та перерахувати фактичні кодові рядки, про які йде мова. Одним із доповнень, який я знайшов корисним, було використання опції grep '--context = n', щоб показати достатню кількість рядків до / після, щоб знати, що таке ім'я файлу (є й інші варіанти grep, які також можуть допомогти в цьому). Тож у моєму випадку другою командою було: git show $ SHAHIT | grep --context = 30 'деякий код'
Дейв Марлі

Відповіді:


57

Хмм, працює для мене:

$ git init
Ініціалізоване порожнє сховище Git у /Users/pknotz/foo/.git/

$ echo "Привіт"> a

$ git додати a

$ git commit -am "початковий коміт"
[master (root-commit) 7e52a51] початковий коміт
 Змінено 1 файл, 1 вставка (+), 0 видалення (-)
 режим створення 100644 a

$ echo "Світ" >> a

$ git commit -am "Будь конкретнішим"
[master 080e9fe] Будьте конкретнішими
 Змінено 1 файл, 1 вставка (+), 0 видалення (-)

$ echo "Привіт"> a

$ git commit -am "Будь менш конкретним"
[master 00f3fd0] Будьте менш конкретними
 Змінено 1 файл, 0 вставок (+), 1 видалення (-)

$ кішка a
Здрастуйте

$ git log -SWorld
зафіксувати 00f3fd0134d0d54aafbb9d959666efc5fd492b4f
Автор: Pat Notz <patnotz@gmail.com>
Дата: вівторок, 6 жовтня 17:20:48, 2009-0600

    Будьте менш конкретними

зафіксувати 080e9fe84ff89aab9d9d51fb5d8d59e8f663ee7f
Автор: Pat Notz <patnotz@gmail.com>
Дата: вівторок, 6 жовтня 17:20:33, 2009-600

    Будьте конкретнішими

Або це не те, що ви маєте на увазі?


1
Ось що я маю на увазі ... Тож, якщо це не працює для мене, може бути, індекс пошкоджений або історія переписана?
Іван

4
У цьому прикладі Pat використовує, git log -SWorldщо не відображає відмінностей. Я здогадуюсь (не пробував), що якби була остання команда, git show 00f3fd0134d0d54aafbb9d959666efc5fd492b4f | grep Worldто ви отримали б поведінку, яку шукаєте.
metasim

2
Це не може бути прийнятою відповіддю, оскільки вона не тільки не відповідає на питання, але й є лише "справою для мене"
Діонісій,

47

git log -S<string>робить роботу, але якщо вам потрібно зробити більш складний пошук, ви можете скористатися git log -G<regex>.

З man:

-G<regex>

Шукайте відмінності, текст виправлення яких містить додані / видалені рядки, які збігаються <regex>.


2

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


Пояснення проблеми

За допомогою '-S' або '-G' ми можемо знайти лише те місце, де його було додано , а не видалено. Для деталізації:

$ git log --format="%H" -S"127.0.124.1"
857aa361293abbb351d6d6becaa55ec011aebc93
$ git show 857aa361293abbb351d6d6becaa55ec011aebc93 | grep "127.0.124.1" # remove grep to see full diff
+       return "127.0.124.1", nil

Крок за кроком

Я отримав ідею від miku86 на dev.to . Спочатку ми намагаємось знайти останній коміт, який існував у нашому рядку:

$ git --no-pager grep "127.0.124.1" $(git rev-list --all) # | head -n1 | cut -d: -f1 # uncomment to only show the hash of the first one
ba0b2d348f4e33857c96acf5a6231cf9d89ddb1b:some/file.go:        return "127.0.124.1"
0d19a98d6434da0b4b5cc2bac190b9b1de36d992:some/file.go:        return "127.0.124.1"
84274c5712bacbbee1dca5567cef77a2b6f356d2:some/file.go:        return "127.0.124.1"
42e692643ff8a5dce7a89e985062b3d38c60fcc0:some/file.go:        return "127.0.124.1"

Що призводить до ba0b2d348f4e33857c96acf5a6231cf9d89ddb1bнашого шуканого коміту. Далі ми намагаємось знайти наступний коміт після цього до HEAD:

$ git rev-list ba0b2d348f4e33857c96acf5a6231cf9d89ddb1b.. # | tail -n1 # uncomment to only show the last one
[...]
c82d040f7be2f8955075655843400a36ceb75303
aa0568b543db57564770d73e736aaf50fd749fb4
dde61dae0cf648e7f4dd8a5c194bcf9be1745793

Що саме dde61dae0cf648e7f4dd8a5c194bcf9be1745793, оскільки це останній у цьому списку, який ми шукаємо.

Отже, ці засоби dde61dae0cf648e7f4dd8a5c194bcf9be1745793повинні містити це видалення?

$ git show dde61dae0cf648e7f4dd8a5c194bcf9be1745793 | grep "127.0.124.1" # remove grep to see full diff
#<no output>

Ні?!? Ну яка різниця тоді від цього до нашого першого знайденого коміту?

$ git diff ba0b2d348f4e33857c96acf5a6231cf9d89ddb1b..dde61dae0cf648e7f4dd8a5c194bcf9be1745793 | grep "127.0.124.1" # remove grep to see full diff
-       return "127.0.124.1"

Ось ми його і знайшли. Це дивно. Але оскільки ми використовуємо різницю між комітами, чи я помилився, і між ними є інші коміти?

$ git log --pretty=oneline ba0b2d348f4e33857c96acf5a6231cf9d89ddb1b..dde61dae0cf648e7f4dd8a5c194bcf9be1745793
dde61dae0cf648e7f4dd8a5c194bcf9be1745793 network interface

Ні, ми, здається, не помилилися. Це дивно. Але так, ось як далеко я дійшов, щоб знайти конкретне місце змін, де рядок зник.


Додатково

Я можу підтвердити , використовуючи , git bisectщо dde61dae0cf648e7f4dd8a5c194bcf9be1745793це Комміт я шукав.

# bisecting a while...
$ git bisect bad 
dde61dae0cf648e7f4dd8a5c194bcf9be1745793 is the first bad commit
commit dde61dae0cf648e7f4dd8a5c194bcf9be1745793
Author: ...
Date:   Fri Oct 18 11:04:26 2019 +0200

    network interface

:100644 100644 242e81c363c2c7069efb018821821553b98f2c97 416c27f5351a9d92a6914b34846c6de51d83dd0d M      go.mod
:040000 040000 715c3ab5b3f4579d8054618f1e11fc05fb425324 e6731408a1ac1ff0428128ccbb1fbfaad4c789ab M      network
[...]

Зверніть увагу, що це git --no-pager grep "127.0.124.1" $(git rev-list --all)працює лише у випадку, якщо у вас є відносно невелика кількість комітів, інакше ви помилилися з помилкою "список аргументів занадто довгий"
simpleuser
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.