git вибіркове відновлення локальних змін з файлу


149

У своєму git repo, який відстежує svn repo, я вніс декілька змін до одного файлу.

Тепер я хочу відновити ці зміни (наприклад, відновити svn), але лише частини файлу.

Я хочу мати можливість переглядати різні файли, відкинути (повернути) зміни, які я не хочу, і зберегти зміни, які я хочу.

то

git add -i 

Здається, що команда має можливість це зробити, але я ще не хочу цього робити.

Відповіді:


91

Це можна зробити безпосередньо за допомогою git checkout -p. Дивіться відповідь Даніеля Штуцбаха нижче.


Стара відповідь (раніше checkout -pбула представлена):

Ви можете це зробити так:

git add -i

(виберіть луки, які ви хочете зберегти)

git commit -m "tmp"

Тепер ви зобов’язані лише зміни, які ви хочете зберегти, а решта не зміниться.

git reset --hard HEAD

На цей момент непослані зміни були відмінені, тому у вас є чистий робочий каталог із змінами, які ви хочете залишати в курсі зверху.

git reset --mixed HEAD^

При цьому видаляється остання фіксація ('tmp'), але зберігаються модифікації у вашій робочій директорії без змін.

EDIT: замінено --softна --mixed, щоб очистити місце постановки.


це вчинить зміни, які я хочу зберегти, чи не так? Я ще не хочу вносити ці зміни. мм, можливо, я ставлюся до занадто серйозно. Можливо, я повинен розслабитися зараз, оскільки це все в місцевому репо. btw, що скидає git --soft HEAD ^ робити?
Pradeep

"git reset --soft HEAD ^" скасовує команду в тому сенсі, що він зберігає робочий каталог та індекс таким, яким він був, і переміщує поточну гілку на один комітет назад.
Якуб Нарубський

Дякую Якубу. Паоло, чому для цього потрібне м'яке скидання голови - 1? часткової фіксації та жорсткого скидання повинно бути достатньо, чи не зберегти деякі зміни та відкинути інші?
Pradeep

1
Відповідь Даніеля нижче - дуже проста і схожа на правильний спосіб зробити це.
Умань

309

Я вважаю, що ви можете це зробити найпростіше за допомогою:

git checkout -p <optional filename(s)>

З сторінки сторінки:

   −p, −−patch
       Interactively select hunks in the difference between the <tree−ish>
       (or the index, if unspecified) and the working tree. The chosen
       hunks are then applied in reverse to the working tree (and if a
       <tree−ish> was specified, the index).
       This means that you can use git checkout −p to selectively discard
       edits from your current working tree.

1
Крім того, якщо ви не хочете робити це вибірково, ви можете використовувати "git checkout - <file> ...", щоб відмовитись від змін.
db42

Чи стосується він каталогів?
bbum

1
Мені здається, це дуже не працює при відхиленні змін ("помилка: патч не змінено <файл>", "помилка: <файл> патч не застосовується"). Як не дивно, я отримаю ці помилки при використанні aопції в патч-режимі, щоб відкинути весь файл, але git checkout -- <file>працює як слід. Хтось знає, чому?
chrnola

У мене була помилка кілька разів, якщо файл вже був виправлений, і тому інтерактивний патч застарів із застосованими патчами поточного файлу. Це сталося під час використання інструменту gui, такого як джерело дерева, якщо я випадково скинув луску двічі. Вдруге призведе до цієї помилки.
фіат

3

Ви можете запустити git diffна файл, зберегти в результаті відмінностей, редагувати його , щоб видалити зміни , які ви дійсно хочете зберегти, а потім запустити його через , patch -Rщоб скасувати решту відмінності.

git diff file.txt> patch.tmp
# редагувати patch.tmp, щоб видалити описи, які ви хочете зберегти
патч -R <patch.tmp

У мене в патч-файлі було 2 штучки, а одного вилучили. Не впевнений, в чому причина, але патч -R продовжує відмовлятися від цього.
Pradeep

2
Ви згадуєте в іншому коментарі, який git diffпоказує весь файл як змінений. Зазвичай це відбувається, коли ви зберегли файл, використовуючи різні закінчення рядків від того, що було раніше. Це також призведе patchдо відхилення файлу патча. Це звучить як те, що могло статися?
Грег Хьюгілл

ти правий. закінчення рядків змінюються щоразу, коли я використовую команду patch. Я на вікнах і використовую крем / вим. Потрібно розібратися в цьому, я думаю,
Pradeep

Я не зміг вирішити проблему з патчем на Windows. Хоча я впевнений, що це працює, я вважаю за краще використовувати рецепт Паоло. Для любові до цих інтерактивних команд для роботи з різницями, використовуючи git add -i.
Pradeep

3

Схоже, ти хочеш

 git revert --no-commit $REVSISON 

Потім можна використовувати

 git diff --cached

щоб побачити, які зміни будуть внесені перед вступом (оскільки повернення - це лише зобов'язання в напрямку вперед, що повторює зворотну зміну в минулому)

Якби у вас було чисте сховище Git, ви, можливо, залежно від своїх цілей, використовуйте інтерактивну базу даних ( git rebase -i), щоб повернутися до комітету, який вам не сподобався, і редагувати комісію заднім числом, щоб зміни, які вам не подобаються, ніколи не відбувалися , але це загально лише для того, якщо ви ЗНАЄте, що більше ніколи не захочете його бачити.


Я повернув, як ви згадували до попередньої редакції (це правильно?), І тепер git diff просто показує весь файл як змінений. Потрібно показати зміни, які я зробив?
Pradeep

1

Перечитавши запитання, це здається, що ви хочете повернути зміни, які є у вашому робочому дереві, а не зміни, які були раніше здійснені, але деякі інші відповіді звучать так, що моє читання може бути неправильним. Ви можете уточнити?

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

git add -i <file>

Потім відкиньте зміни, які ви не хочете зберігати, перевіривши версію індексу:

git checkout -- <file>

Тоді зніміть зміни, якщо ви ще не хочете, щоб вони були поетапними:

git reset -- <file>

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

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

git reset <commit_before_first_unwanted_change> -- <file>

Тоді ви можете дотримуватися попереднього рецепту, git add -i <file>щоб поетапно змінити ті зміни, які ви хочете зберегти, git checkout -- <file>викинути небажані зміни та git reset -- <file>"невдало" зміни.


0

Параметри командного рядка, описані у відповідях тут, зручні, коли файл знаходиться на сервері, до якого я отримую доступ через термінал ssh. Однак, коли файл знаходиться на моїй локальній машині, я віддаю перевагу наступному способу:

Відкрийте файл у редакторі netbeans (який постачається із підтримкою git). Netbeans ставить червоні / зелені / сині позначки під номерами рядків, щоб вказати, де матеріал був видалений / доданий / змінений (відповідно).

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

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