Чи можу я зробити часткове відновлення в 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.