Как изменить последний коммит, чтобы удалить файл?

108

Я изменил два файла a, bв последней фиксации. Но файл bне должен быть зафиксирован, каков рабочий процесс, чтобы исправить это?

Xiè Jìléi
источник

Ответы:

109

Обновление (пару лет спустя)

Ян Худек

Удалить его из индекса просто.

Верно: вы можете легко восстановить файл до его индексного содержимого, как предлагает более поздний ответ (написанный Мэттом Коннолли ):

git reset HEAD^ path/to/file/to/revert

HEAD^позволяет файлу получить доступ к его содержимому в предыдущем коммите перед последним.

Тогда вы можете git commit --amend, как я изначально писал ниже.


С Git 2.23 (август 2019 г.) вы можете использовать новую git restoreкоманду

 git restore --source=HEAD^ --staged  -- path/to/file/to/revert

короче:

 git restore -s@^ -S -- path/to/file/to/revert

Опять же, вы можете git commit --amend, как я изначально писал ниже.


Оригинальный ответ (январь 2011 г.)

Если это ваш последний коммит (и вы его нигде не нажимали), вы можете изменить его:
(сначала спрятать или сохранить b)

 git commit --amend

Затем удалите b, повторите коммит. Восстановите б, и все готово.

--amend

Используется для изменения кончика текущей ветки.
Подготовьте объект дерева, который вы хотели бы заменить последним коммитом, как обычно (это включает в себя обычный -i / -o и явные пути), и редактор журнала коммитов будет заполнен сообщением коммита из кончика текущей ветви.
Созданный вами коммит заменяет текущий совет - если это было слияние, родители текущего совета будут иметь родителей, поэтому текущий верхний коммит отбрасывается.

VonC
источник
... Then stash/delete b, re-commit.., Здесь не должно слово Thenбыть after? - --amendпосле удаления / удаления b, ...
Xiè Jìléi
@ 谢 继 雷: другими словами, сначала сохраните b, затем подтвердите --amend, а затем восстановите? Правда. Я обновил ответ.
VonC
С помощью git index указывать кому-либо сохранять / сохранять файл просто глупо (-1). Удалить его из индекса просто.
Ян Худек
1
@JanHudec Правда, я соответственно отредактировал ответ. Я не следовал этому старому ответу так внимательно, как в случае переполнения стека. В любом случае 99% git-вопросов по SU должны быть перенесены на SO.
VonC
66
  1. git diff --name-only HEAD^ - (необязательно) использовать для отображения файлов, которые изменились за последний коммит.
  2. git reset HEAD^ path/to/file/to/revert- сбросить индекс до последней версии, оставив рабочую копию нетронутой.
  3. git commit --amend- изменить этот последний коммит, чтобы включить изменения индекса
Мэтт Коннолли
источник
9
Имхо, это гораздо лучший ответ, чем принятый.
mik01aj
1
Обратите внимание, что вы не должны использовать git commit -a --amend(т. Е. Не добавлять файлы) на шаге 3, иначе вы внесете изменения в рабочую копию, которые вы пытаетесь удалить. Необязательный шаг 2.5 может также привести git checkout path/to/file/to/revertк очистке вашей рабочей копии.
13
1
Также git rm --cached path/to/file/to/revertможно удалить файл, не удаляя его из дерева.
Ян Худек
13

В качестве альтернативы, если вы используете git gui, вы просто выбираете опцию «Amend last commit», добавленный файл появляется в списке «Staged», кликаете по его значку, чтобы переместить его в список «Unstaged» и делаете коммит.

Ян Худек
источник
1
@VonC: Редактирование и разделение патчей - довольно распространенная операция для активных пользователей git, поэтому графический интерфейс был разработан, чтобы упростить его, и является лучшим инструментом IMO для этого.
Ян Худек
Это работает! У меня не было успеха с другими вариантами для этой конкретной задачи. Спасибо за чаевые!
Сергузест
10

Если вы хотите удалить b из вашего последнего коммита

git rm --cached b (will preserve the file in the working tree but remove it from the index)
git commit --amend

Если вы хотите удалить все изменения в b в вашем последнем коммите

(backup b)
(modify b to state before incorrect commit)
git commit --amend
(restore b)
Pingo
источник
git rm --cachedи покончить с резервным копированием / восстановлением танца (-1).
Ян Худек
Спасибо что подметил это. Я хотел поделиться тем, как я это сделал, потому что это был подход, который мне удобнее всего даже после прочтения всей цепочки.
Пинго
4

Альтернатива, которая не требует взлома индекса, но тем не менее сохраняет старое сообщение коммита:

$ git reset HEAD^
$ git add <all the files you want, excluding the one you don't want>
$ git commit -C HEAD@{1}

Мне это нравится, потому что (а) он использует команды, которые я регулярно использую, и (б) я могу сделать, git add -pчтобы выяснить, что именно я хочу зафиксировать.

Джастин Л.
источник