Просто комментарий:
git revert aCommit
возвращает все коммит (как в « все файлы часть коммита»):
он вычисляет обратный патч, применяет его к HEAD и фиксирует.
Итак, две проблемы здесь (первая легко решаема):
- он всегда фиксирует, так что вы можете добавить
-no-commit
параметр: "git revert --no-commit aCommit
": это полезно при возврате эффекта более одного коммита в ваш индекс в строке.
- это не относится к конкретному файлу (что, если вы a.py входили в коммит с 1000 другими изменениями, которые вы, возможно, не захотите отменить)?
Для этого, если вы хотите извлечь определенные файлы, как они были в другом коммите, вы должны увидеть git-checkout
, в частности синтаксис git checkout <commit> <filename>
(который это не совсем то, что вам нужно в этом случае)
Easy Git (Элайджа Ньюрен) пытался внести более "полный возврат" в список рассылки Git ; но без особого успеха:
Люди иногда хотят «отменить изменения».
Теперь это может быть:
- изменения между 32 и 29 ревизиями назад,
- это могут быть все изменения с момента последнего коммита,
- это могут быть изменения с 3 коммитов назад или
- это может быть только один конкретный коммит.
- Пользователь может захотеть поместить такие реверсии только в определенные файлы ,
(eg revert
здесь задокументировано , но я не уверен, что это часть текущего распределения, например, хотя)
но все это сводится к "отмене изменений" в конце.
eg revert --since HEAD~3 # Undo all changes since HEAD~3
eg revert --in HEAD~8 # much like git revert HEAD~8, but nocommit by default
eg revert --since HEAD foo.py # Undo changes to foo.py since last commit
eg revert foo.py # Same as above
eg revert --in trial~7 bar.c baz. # Undo changes made in trial~7 to bar.[ch]
Действительно ли эти виды «возврата данных» настолько различны, что должны быть разные команды, или что некоторые из этих операций не должны поддерживаться простой командой возврата?
Конечно, большинство пользователей большую часть времени, вероятно, будут использовать "eg revert FILE1 FILE2...
"
форма, но я не видел вреда в поддержке дополнительных возможностей.
Кроме того ... есть ли что-то фундаментальное, что удерживало бы ядро от такого поведения?
Элайджа
Примечание: коммиты по умолчанию не имеют смысла для обобщенной команды revert
, и "git revert REVISION
" выдает ошибку с инструкциями (сообщающими пользователю добавить флаг --in).
Допустим, у вас есть из 50 подтвержденных 20 файлов, которые, как вы понимаете, в старой фиксации X были внесены изменения, которых не должно было быть.
Немного сантехники в порядке.
Что вам нужно, это способ перечислить все конкретные файлы, которые вам нужно вернуть
(как в «отменить изменения, сделанные в коммите X, сохранив все последующие изменения» ),
а затем для каждого из них:
git-merge-file -p a.py X X^
Проблема здесь в том, чтобы восстановить потерянную функцию без удаления всех последующих изменений в a.py, которые вы, возможно, захотите сохранить.
Эту технику иногда называют «негативным слиянием».
С git merge-file <current-file> <base-file> <other-file>
означает :
включает все изменения, которые ведут от <base-file>
к <other-file>
в <current-file>
, вы можете восстановить удаленную функцию, сказав, что хотите включить все изменения.)
- из: X (где функция была удалена)
- to: X ^ (предыдущий коммит до X, где функция все еще была там)
Примечание: аргумент '-p
' , который позволяет вам сначала просмотреть изменения, ничего не делая с текущим файлом. Если вы уверены, удалите эту опцию.
Примечание : git merge-file
это не так просто : вы не можете ссылаться на предыдущие версии файла просто так.
(у вас снова и снова появляется разочаровывающее сообщение: error: Could not stat X
)
Вы должны:
git cat-file blob a.py > tmp/ori # current file before any modification
git cat-file blob HEAD~2:a.py > tmp/X # file with the function deleted
git cat-file blob HEAD~3:a.py > tmp/F # file with the function which was still there
git merge-file a.py tmp/X tmp/F # basically a RCS-style merge
# note the inversed commit order: X as based, then F
# that is why is is a "negative merge"
diff -u a.py tmp/ori # eyeball the merge result
git add a.py
git commit -m "function restored" # and any other changes made from X are preserved!
Если это должно быть сделано для большого количества файлов в рамках предыдущего коммита ... некоторые сценарии в порядке;)