Чи можу я зробити часткове відновлення в GIT


156

Чи можливо повернути лише один файл або певні зміни у файлі у багатофайловій комісії?

Повна історія я зробила купу файлів. Через декілька комітетів хтось, хто залишиться без імені (JACK !!!), скопіював файл у своє сховище та вніс декілька файлів, перезаписавши деякі зміни, які я вніс. Я хочу повернути один файл, який вийшов з клобіру чи ще краще, увійдіть і відновіть дві зміни у цьому файлі. Це повинно бути окремим зобов'язанням відновити, оскільки воно було витягнуто та натиснуто.


Брайан вивів мене на правильний шлях. Я в кінцевому підсумку використовував git add --patch, потім використовуючи функцію редагування в патчі, щоб отримати те, що хотів.
Зчеплення

2
Я досить запізнююся на гру, але думаю, що знайшов "правильну" відповідь .
ntc2

@ ntc2 Як не дивно, прийнята відповідь працювала для мене набагато краще, ніж та, яку ви пов’язали - це створило конфлікти для злиття для мене, щоб вирішити, а не просто не застосувати патчі.
Ірідаїн

@liridayn Ви читали всю мою відповідь? У розділі "Варіації" я стверджую, що додавання --3wayпризводить до конфліктів злиття замість того, щоб не застосувати виправлення.
ntc2

Відповіді:


204

Ви можете скасувати комісію, не створюючи нову, додавши опцію "--no-commit". Це залишає всі повернені файли в області постановки. Звідти я б здійснив плавне скидання і додав до змін, які мені дуже хотілося. Для прикладу робочого процесу:

git revert <sha-of-bad-commit> --no-commit
git reset   // This gets them out of the staging area
<edit bad file to look like it should, if necessary>
git add <bad-file>
git checkout . // This wipes all the undesired reverts still hanging around in the working copy
git commit

42
Після програмного скидання можна також git add -pзапустити інтерактивний сеанс, який дозволяє вибірково додавати шматки файлів замість цілих файлів. (Є також git reset -pвибірково нестабільні зміни. Добре знати, але, мабуть, не те, що ви хочете в цьому сценарії.)
Stéphan Kochen

1
Це саме те, що я шукав: поверніться до робочої копії, виберіть хунки інтерактивно, виконайте завдання. Ти заслуговуєш на це великого солоного чоловіка: *
das_weezul

Іншим рішенням натхненний цей буде revert, reset, stash -p(заначка "скасовує , що я не хочу , щоб actualy марки»), addінші,commit
Кирило Chapon

82

За допомогою команди можна інтерактивно застосувати стару версію файлу checkout.

Наприклад, якщо ви знаєте, COMMITкуди було видалено код для додавання, можна виконати таку команду:

git checkout -p COMMIT^ -- FILE_TO_REVERT

Git запропонує вам додати назад файли, які відсутні у поточній версії файлу. Ви можете використовувати eдля створення виправлення зміни перед тим, як застосувати її назад.


Дуже корисно, якщо ви хочете відновити лише частину файлу! В основному, щоб отримати шматки з голови,git checkout -p path/to/file
falstaff

40

Ви можете просто вручну перевірити старий добрий вміст файлів, які ви хочете відновити git checkout. Наприклад, якщо ви хочете повернутися my-important-fileдо версії, яка була у версії abc123, ви можете зробити це

git checkout abc123 -- my-important-file

Тепер у вас є старий вміст my-important-fileназад, і ви можете навіть редагувати їх, якщо вам здається, і взяти на себе зобов’язання зробити зобов’язання, яке поверне зміни, які він вніс. Якщо ви хочете відновити лише деякі частини його комісії, використовуйте git add -pдля вибору лише декілька згорток із патча, який ви здійснюєте.


19
Це не revertви, ви просто берете назад стару версію файлу. Належний revertфайл видалить неправильні зміни фіксації у файлі, навіть якщо вони були змінені кілька разів з тих пір, і ви не хочете втрачати ці зміни.
Тотор

2
Тоторе, дивіться мою відповідь. Ви можете використовувати '-p' для збереження модифікацій. Відповідь насправді дуже близька до цієї.
cmcginty

1
Або ви можете об'єднати це в git checkout -p.
Лео Лам

31

Я знайшов спосіб зробити це у списку розсилки Git:

git show <commit> -- <path> | git apply --reverse

Джерело: http://git.661346.n2.nabble.com/Revert-a-single-commit-in-a-single-file-td6064050.html#a6064406

Варіації

Ця команда виходить з ладу (не спричиняючи жодних змін), якщо патч не застосовується чисто, але --3wayнатомість у вас виникають конфлікти, які ви зможете вирішити вручну (у цьому випадку відповідь Кейсі може бути більш практичною):

git show <commit> -- <path> | git apply --reverse --3way

Ви також можете використовувати це для часткового повернення кількох комітетів, наприклад:

git log -S<string> --patch | git apply --reverse

відновити файли зі змінами, які відповідають <string>будь-якому комітету. Це саме те, що мені було потрібно у моєму випадку використання (декілька окремих комісій внесли подібні зміни до різних файлів, а також зміни інших файлів непов'язаними способами, які я не хотів відновити).

Якщо ви diff.noprefix=trueвстановили в своєму, ~/.gitconfigвам потрібно додати -p0до git applyкоманди, наприклад

git show <commit> -- <path> | git apply -p0 --reverse

Ця відповідь набагато краща за прийняту: "ще краще, увійдіть і відновіть дві зміни у цьому файлі".
переписано

Я хотів повернути лише частину коміту, тому зробив: (1) git show ... > foo.txt (2) редагування, foo.txtщоб видалити diff, я хотів не повернути (3), git apply --reverse foo.txt щоб повернути diff, які все ще перераховані в foo.txt.
cxw

Додавання --binary --full-index до git show part також може стати корисною варіацією
Laurynas Biveinis
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.