Повернення частини комітету з git


144

Я хочу повернути певний комітет у git. На жаль, наша організація все ще використовує CVS як стандарт, тому коли я повертаюсь до CVS, декілька коміксів git об'єднуються в одну. У цьому випадку я хотів би виділити оригінальний git počin, але це неможливо.

Чи існує такий підхід, git add --patchякий би дозволив мені вибірково редагувати різницю, щоб вирішити, які частини зобов'язання відновити?


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

Відповіді:


226

Використовуйте опцію --no-commit( -n) git revert, а потім зніміть зміни, а потім скористайтеся git add --patch:

$ git revert -n $bad_commit    # Revert the commit, but don't commit the changes
$ git reset HEAD .             # Unstage the changes
$ git add --patch .            # Add whatever changes you want
$ git commit                   # Commit those changes

Примітка. Файли, які ви додаєте за допомогою git add --patch, - це файли, які ви хочете відновити, а не файли, які ви хочете зберегти.


13
Можливо, варто додати остаточну необхідну команду для тих, хто не так знайомий з git: після вчинення, git reset --hardвідмовитися від інших змін, які ви не хотіли відновити.
тремтіння

15
git reset --hardнебезпечно для новачків, оскільки може втратити потрібні зміни. Замість цього звикайте git status, це натякає на те, git checkout -- FILE..щоб повернути речі більш безпечно.
Тіно

Який зефір git; git revertслід просто взяти --patchаргумент.
Каз

@Kaz: git revertвикористовується для відновлення цілих комірок . Ви можете використовувати git checkout -pдля інтерактивного вибору бітів для відновлення.
mipadi

1
Я також хотів би додати (можливо) очевидне, що спочатку збережіть вашу роботу . Або commitспочатку, або stash, потім спробуйте revert.
Феліпе Альварес

39

Я успішно використовував наступне.

Спочатку скасуйте повну комісію (ставить її в індекс), але не здійснюйте.

git revert -n <sha1>  # -n is short for --no-commit

Потім інтерактивно видаліть повернені ДОБРІ зміни з індексу

git reset -p          # -p is short for --patch  

Потім здійснити зворотну різницю поганих змін

git commit -m "Partially revert <sha1>..."

Нарешті, повернені ДОБРІ зміни (які були невибрані командою скидання) все ще знаходяться в робочому дереві. Їх потрібно прибрати. Якщо в робочому дереві не залишилося жодних неспроможних змін, це можна зробити

git reset --hard

5
Чи це не чудова альтернатива прийнятої відповіді (яка використовує reset HEAD .), оскільки вона не потребує остаточного очищення робочого режиму?
Стівен Лу

2
Ця відповідь є вищою, тому що reset -pвона коротша, ніж reset HEADдалі add -p. Але це все ще вимагає прибирання, оскільки «добрі» номери, які були скинуті, все ще знаходяться в робочому каталозі після завершення.
Chiel ten Brinke

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

5

Особисто я віддаю перевагу цій версії, яка повторно використовує автоматично сформоване повідомлення про фіксацію та дає користувачеві можливість редагувати та вставляти слово "Частково", перш ніж остаточно здійснити.

# generate a revert commit
# note the hash printed to console on success
git revert --no-edit <hash to revert>

# undo that commit, but not its changes to the working tree
# (reset index to commit-before-last; that is, one graph entry up from HEAD)
git reset HEAD~1

# interactively add reversions
git add -p

# commit with pre-filled message
git commit -c <hash from revert commit, printed to console after first command>

# reset the rest of the current directory's working tree to match git
# this will reapply the excluded parts of the reversion to the working tree
# you may need to change the paths to be checked out
# be careful not to accidentally overwrite unsaved work
git checkout -- .

4

Рішення:

git revert --no-commit <commit hash>
git reset -p        # every time choose 'y' if you want keep the change, otherwise choose 'n'
git commit -m "Revert ..."
git checkout -- .   # Don't forget to use it.

Це допомогло б людям, якби ви сказали, чим воно відрізняється від прийнятого рішення
CharlesB

1
@Krzysztof Чому замовлення в кінці є важливим і чому це рішення відрізняється від рішення користувача1338062?
Мартін

3

Інша альтернатива (якщо ваша поточна версія файлу не надто далека від версії, яку ви намагаєтеся відновити), - це отримати хеш комісії безпосередньо перед тією, яку ви хочете частково повернути (з git log). Тоді ваша команда стає:

$ git checkout -p <hash_preceding_commit_to_revert> -- file/you/want/to/fix.ext

Це змінює файли у вашому робочому дереві, але не створює жодних комісій, тож якщо ви дійсно налаштовані, ви можете просто почати знову git reset --hard -- file/you/want/to/fix.ext.


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