Как изменить существующие, нечеткие коммиты?

7686
голосов

Я написал неправильную вещь в сообщении фиксации. Кроме того, я забыл включить некоторые файлы.

Как изменить сообщение/файлы фиксации? Конец еще не нажат.

задан Laurie Young 07 окт. '08 в 18:44
источник

27 ответов

14066
голосов

Изменение последнего сообщения о фиксации

git commit --amend

откроет ваш редактор, позволяя вам изменить сообщение фиксации последнего коммита. Кроме того, вы можете установить сообщение commit непосредственно в командной строке:

git commit --amend -m "New commit message"

... однако, это может сделать многострочные сообщения фиксации или небольшие исправления более громоздкими для ввода.

Перед тем, как сделать это, убедитесь, что у вас нет каких-либо изменений в рабочей копии, иначе они также будут совершены. (Нестационарные изменения не будут зафиксированы.)

Изменение сообщения о фиксации, которое вы уже нажали на удаленную ветвь

Если вы уже нажали свою фиксацию на удаленную ветку, то вы должны принудительно нажать фиксацию с помощью:

git push <remote> <branch> --force
# Or
git push <remote> <branch> -f

Предупреждение: принудительное нажатие перезапишет удаленную ветвь с состоянием вашего локального. Если на удаленной ветке есть коммиты, которых у вас нет в локальной ветке, вы потеряете эти коммиты.

Предупреждение: будьте осторожны при внесении изменений в коммиты, которые вы уже поделили с другими людьми. Внесение поправок, по сути, переписывает их, чтобы иметь разные SHA, что создает проблему, если у других людей есть копии старой фиксации, которую вы переписали. Любой, у кого есть копия старого коммита, должен будет синхронизировать свою работу с вашим недавно переписанным фиксатором, что иногда может быть затруднено, поэтому убедитесь, что вы координируете работу с другими при попытке переписать общую историю фиксаций или просто не переписываете общие коммиты в целом.


Использовать интерактивную переадресацию

Другой вариант - использовать интерактивную rebase.
Это позволяет редактировать любое сообщение, которое вы хотите обновить, даже если оно не является последним.

Чтобы выполнить сквош git, выполните следующие действия:

// X is the number of commits to the last commit you want to be able to edit
git rebase -i HEAD~X

После того, как вы раздавите свои коммиты - выберите e/r для редактирования сообщения

введите описание изображения здесь

Важное примечание об интерактивной переадресации

Когда вы используете git rebase -i HEAD~X, может быть больше, чем X. git будет "собирать" все коммиты в последнем объявлении X, и если бы произошло слияние где-то между этим диапазоном, вы также увидите все коммиты, поэтому результат будет X +.

Хороший совет:

Если вам нужно сделать это для более чем одной ветки, и вы можете столкнуться с конфликтами при изменении содержимого, настройте git rerere и разрешите git эти конфликты автоматически для вас.


Документация

ответ дан EfForEffort 07 окт. '08 в 18:50
источник
2323
голосов
git commit --amend -m "your new message"
ответ дан lfx_cool 08 февр. '10 в 7:26
источник
2224
голосов

Если фиксация, которую вы хотите исправить, не является последней:

  • git rebase --interactive $parent_of_flawed_commit

    Если вы хотите исправить несколько ошибочных коммитов, передайте родительский код самого старого из них.

  • Появится редактор со списком всех коммитов с тех пор, как вы дали.

    • Измените pick на reword (или на старые версии Git, на edit) перед любыми фиксациями, которые вы хотите исправить.
    • После сохранения Git воспроизведет перечисленные коммиты.

  • Для каждой фиксации, которую вы хотите переделать, Git вернет вас обратно в ваш редактор. Для каждой фиксации, которую вы хотите изменить, Git помещает вас в оболочку. Если вы находитесь в оболочке:

    • Измените фиксацию любым способом.
    • git commit --amend
    • git rebase --continue

Большая часть этой последовательности будет объясняться вам по выходу различных команд по ходу. Его очень легко, вам не нужно запоминать его - просто помните, что git rebase --interactive позволяет вам исправлять, независимо от того, как давно они были.


Обратите внимание, что вы не захотите изменять фиксации, которые вы уже нажали. Или, может быть, вы это сделаете, но в этом случае вам придется проявлять большую осторожность, чтобы общаться со всеми, кто, возможно, потянул ваши коммиты и сделал работу поверх них. Как восстановить/пересинхронизировать после того, как кто-то перетащил rebase или reset в опубликованную ветку?

ответ дан Aristotle Pagaltzis 07 окт. '08 в 22:52
источник
719
голосов

Чтобы внести изменения в предыдущую фиксацию, внесите необходимые изменения и выполните эти изменения, а затем запустите

git commit --amend

Это откроет файл в текстовом редакторе, представляющем ваше новое сообщение фиксации. Он начинает заполняться текстом из вашего старого сообщения фиксации. Измените сообщение фиксации так, как вы хотите, затем сохраните файл и завершите работу редактора.

Чтобы изменить предыдущую фиксацию и сохранить одно и то же сообщение журнала, запустите

git commit --amend -C HEAD

Чтобы исправить предыдущую фиксацию, полностью удалив ее, запустите

git reset --hard HEAD^

Если вы хотите отредактировать несколько сообщений фиксации, запустите

git rebase -i HEAD~commit_count

(Замените commit_count на количество коммитов, которые вы хотите изменить.) Эта команда запускает ваш редактор. Отметьте первый фиксатор (тот, который вы хотите изменить) как "редактировать" вместо "выбрать", затем сохраните и выйдите из редактора. Внесите изменения, которые вы хотите зафиксировать, а затем запустите

git commit --amend
git rebase --continue

Примечание. Вы можете "Сделать желаемое изменение" также из редактора, открытого git commit --amend

ответ дан Fatih 16 авг. '11 в 0:20
источник
367
голосов

Как уже упоминалось, git commit --amend - это способ перезаписать последнее коммит. Одна заметка: если вы хотите также перезаписать файлы, команда будет

git commit -a --amend -m "My new commit message"
ответ дан John 07 июня '11 в 0:16
источник
332
голосов

Вы также можете использовать git filter-branch для этого.

git filter-branch -f --msg-filter "sed 's/errror/error/'" $flawed_commit..HEAD

Это не так просто, как тривиальный git commit --amend, но он особенно полезен, если у вас уже есть некоторые слияния после вашего сообщения о ошибочной фиксации.

Обратите внимание, что это попытается переписать КАЖДОЙ фиксацию между HEAD и ошибочным фиксацией, поэтому вы должны выбрать команду msg-filter очень мудрую; -)

ответ дан Mark 01 сент. '12 в 23:35
источник
297
голосов

Я предпочитаю этот путь.

git commit --amend -c <commit ID>

В противном случае будет новый коммит с новым идентификатором фиксации

ответ дан krevedko 10 янв. '13 в 17:23
источник
280
голосов

Если вы используете инструмент Git GUI, есть кнопка с именем last last commit. Нажмите на эту кнопку, а затем отобразите свои последние файлы фиксации и сообщение. Просто отредактируйте это сообщение, и вы можете зафиксировать его с новым сообщением фиксации.

Или используйте эту команду с консоли/терминала:

git commit -a --amend -m "My new commit message"
ответ дан Akhilraj N S 08 нояб. '12 в 6:51
источник
273
голосов

Вы можете использовать Git rebasing. Например, если вы хотите изменить back to commit bbc643cd, запустите

$ git rebase bbc643cd^ --interactive

В редакторе по умолчанию измените 'pick' на 'edit' в строке, чью фиксацию вы хотите изменить. Внесите изменения, а затем выполните их с помощью

$ git add <filepattern>

Теперь вы можете использовать

$ git commit --amend

чтобы изменить фиксацию, и после этого

$ git rebase --continue

чтобы вернуться к предыдущему фиксации главы.

ответ дан Shoaib Ud-Din 22 янв. '13 в 20:23
источник
264
голосов
  • Если вы хотите изменить последнее сообщение о фиксации, выполните следующие действия:

    git commit --amend
    

    Это приведет вас к вашему текстовому редактору и позволит вам изменить последнее сообщение фиксации.

  • Если вы хотите изменить последние 3 сообщения фиксации или любые сообщения о фиксации до этой точки, поставьте HEAD~3 в команду git rebase -i:

    git rebase -i HEAD~3
    
ответ дан Heena Hussain 22 окт. '12 в 14:22
источник
243
голосов

Если вам нужно изменить старое сообщение фиксации на несколько ветвей (т.е. сообщение с ошибочным сообщением присутствует в нескольких ветвях), вы можете использовать:

git filter-branch -f --msg-filter \
'sed "s/<old message>/<new message>/g"' -- --all

Git создаст временный каталог для перезаписи и дополнительно резервное копирование старых ссылок в refs/original/.

  • -f обеспечит выполнение операции. Это необходимо, если временный каталог уже присутствует или имеются уже ссылки, хранящиеся в refs/original. Если это не так, вы можете удалить этот флаг.

  • -- отделяет параметры ветвления фильтра от параметров ревизии.

  • --all будет гарантировать, что все ветки и теги будут перезаписаны.

Из-за резервного копирования ваших старых ссылок вы можете легко вернуться к состоянию перед выполнением команды.

Скажем, вы хотите восстановить свой мастер и получить доступ к нему в ветке old_master:

git checkout -b old_master refs/original/refs/heads/master
ответ дан sebers 15 нояб. '12 в 12:29
источник
207
голосов

Использование

git commit --amend

Чтобы понять это подробно, отличный пост 4. Перезапись Git История. Он также говорит о , когда не использовать git commit --amend.

ответ дан skin 27 марта '13 в 23:43
источник
185
голосов

Внести поправки

У вас есть пара вариантов. Вы можете сделать

git commit --amend

до тех пор, пока оно не будет выполнено последним.

Интерактивная переадресация

В противном случае, если это не ваша последняя фиксация, вы можете выполнить интерактивную перезагрузку,

git rebase -i [branched_from] [hash before commit]

Затем внутри интерактивной переадресации вы просто добавляете редактирование этого коммита. Когда это произойдет, сделайте git commit --amend и измените сообщение фиксации. Если вы хотите вернуться назад до этой точки фиксации, вы также можете использовать git reflog и просто удалить эту фиксацию. Затем вы снова выполните git commit.

ответ дан wallerjake 18 янв. '13 в 4:45
источник
171
голос

Если вы используете графический интерфейс Git, вы можете изменить последнее коммит, который не был нажат:

Commit/Amend Last Commit
ответ дан gulchrider 01 дек. '12 в 8:03
источник
156
голосов

Я использую Git GUI столько, сколько могу, и это дает вам возможность изменить последнее сообщение:

Tick that box

Кроме того, git rebase -i origin/master - это хорошая мантра, которая всегда будет представлять вас с фиксациями, сделанными вами поверх мастера, и дает вам возможность изменять, удалять, изменять порядок или сквош. Не нужно сначала захватить этот хэш.

ответ дан Havard Graff 05 авг. '13 в 2:13
источник
153
голосов

Если это ваша последняя фиксация, просто исправить commit:

git commit --amend -o -m "New commit message"

(используя флаг -o (--only), чтобы убедиться, что вы изменяете только сообщение фиксации)


Если он похож на коммит, используйте удивительную интерактивную rebase:

git rebase -i @~9   # Show the last 9 commits in a text editor

Найдите требуемую фиксацию, измените pick на r (reword) и сохраните и закройте файл. Готово!



Миниатюрный учебник vim (или, как переустановить всего 8 нажатий клавиш 3j cw r Esc ZZ):

  • Запустите vimtutor, если у вас есть время
  • h j k l соответствуют клавишам перемещения
  • Все команды могут иметь префикс "диапазон", например. 3j перемещается на 3 строки
  • i, чтобы войти в режим вставки - текст, который вы вводите, появится в файле
  • Esc или Ctrl c, чтобы выйти из режима вставки и вернуться в "обычный" режим
  • u для отмены
  • Ctrl r для повтора
  • dd, dw, dl, чтобы удалить строку, слово или букву, соответственно
  • cc, cw, cl, чтобы изменить строку, слово или букву соответственно (то же самое, что dd i)
  • yy, yw, yl для копирования ( "yank" ) строки, слова или буквы, соответственно
  • p или p для вставки после или до текущей позиции соответственно
  • :w Enter для сохранения (записи) файла
  • :q! Enter выйти без сохранения
  • :wq Enter или ZZ для сохранения и выхода

Если вы много редактируете текст, переключитесь на раскладку клавиатуры Dvorak, научитесь касаться и изучите vim. Стоит ли усилий? Да.



ProTip ™: не бойтесь экспериментировать с "опасными" командами, которые переписывают историю * - Git не удаляет ваши фиксации в течение 90 дней по умолчанию; вы можете найти их в reflog:

$ git reset @~3   # go back 3 commits
$ git reflog
c4f708b HEAD@{0}: reset: moving to @~3
2c52489 HEAD@{1}: commit: more changes
4a5246d HEAD@{2}: commit: make important changes
e8571e4 HEAD@{3}: commit: make some changes
... earlier commits ...
$ git reset 2c52489
... and you're back where you started

* Остерегайтесь таких параметров, как --hard и --force, хотя они могут отбрасывать данные.
* Также не переписывайте историю в каких-либо ветких, с которыми вы сотрудничаете.

ответ дан Zaz 10 февр. '15 в 3:01
источник
125
голосов

Ничего себе, поэтому есть много способов сделать это.

Еще один способ сделать это - удалить последнее коммит, но сохранить его изменения, чтобы вы не потеряли свою работу. Затем вы можете выполнить другое коммитирование с исправленным сообщением. Это будет выглядеть примерно так:

git reset --soft HEAD~1
git commit -m 'New and corrected commit message'

Я всегда делаю это, если забываю добавить файл или внести изменения.

Помните, чтобы указать --soft вместо --hard, иначе вы полностью потеряете эту фиксацию.

ответ дан Radu Murzea 03 дек. '13 в 0:31
источник
114
голосов

Если вы хотите изменить последнее использование фиксации:

git commit --amend

или

git commit --amend -m 'one line message'

Но если вы хотите отредактировать несколько коммитов в строке, вы должны вместо этого использовать rebasing:

git rebase -i <hash of one commit before the wrong commit>

git rebase editing

В файле, подобном приведенному выше, напишите edit/e или один из других параметров и нажмите "Сохранить" и "Выход".

Теперь вы будете в первом неправильном коммите. Внесите изменения в файлы, и они будут автоматически организованы для вас. Тип

git commit --amend

сохранить и выйти из него и набрать

git rebase --continue 

чтобы перейти к следующему выбору, пока не закончите со всеми вашими выборами.

Обратите внимание, что эти вещи меняют все ваши хэши SHA после этой конкретной фиксации.

ответ дан Shubham Chaudhary 07 янв. '14 в 1:03
источник
114
голосов

Если вы хотите изменить последнее сообщение, вы должны использовать флаг --only или его ярлык -o с помощью commit --amend:

git commit --amend -o -m "New commit message"

Это гарантирует, что вы не случайно улучшите свое совершение с помощью поставленных вещей. Конечно, лучше иметь правильную конфигурацию $EDITOR. Затем вы можете оставить параметр -m, а git предварительно заполнит сообщение фиксации старым. Таким образом, его можно легко отредактировать.

ответ дан David Ongaro 23 мая '14 в 11:40
источник
106
голосов

Для тех, кто ищет графический интерфейс Windows/Mac, чтобы редактировать больше, чем просто последнее сообщение (для unpushed commits), я бы рекомендовал SourceTree.

Обновление: с тех пор как обнаруженная процедура ниже описана более подробно, с более скриншотами и дополнительными шагами для того, когда коммиты были нажаты в этот ответ.

SourceTree interactive rebase

Процедура:

  • Убедитесь, что вы зафиксировали или спрятали все текущие изменения (т.е. нет файлов, перечисленных на вкладке "Состояние файла" - это не будет работать иначе).
  • На вкладке "Журнал/история" щелкните правой кнопкой мыши на записи с соседней строкой в ​​графе ниже фиксации, которую вы хотите отредактировать, и выберите "Rebase children of < commit ref > интерактивно..."
  • Выберите целую строку для сообщения фиксации, которое вы хотите изменить (т.е. щелкните по столбцу "Сообщение" ).
  • Нажмите кнопку "Редактировать сообщение".
  • Отредактируйте сообщение по желанию в появившемся диалоговом окне и нажмите "ОК".
  • Повторите шаги 3-4, если есть другие сообщения для изменения.
  • Нажмите "ОК" - начнется перезагрузка - если все будет хорошо, вывод завершится "Завершено успешно".
ответ дан Steve Chambers 06 нояб. '14 в 18:01
источник
90
голосов

Обновите последнее ошибочное сообщение с новым сообщением о фиксации в одной строке:

git commit --amend -m "your new commit message"

Или попробуйте git reset, как показано ниже:

# You can reset your head to n number of commit
# NOT a good idea for changing last commit message
# but you can get an idea to split commit into multiple commits
git reset --soft HEAD^

# it will reset you last commit. Now, you
# can re-commit it with new commit message.

Использование reset для разделения коммитов на более мелкие коммиты

git reset может помочь вам разбить одно коммит на несколько коммитов:

# reset your head. I am resetting to last commits:
git reset --soft HEAD^
# (you can reset multiple commit by doing HEAD~2(no. of commits)

# Now, reset your head for splitting it to multiple commits
git reset HEAD

# add and commit your files seperately to make multiple commits: e.g
git add app/
git commit -m "add all files in app directory"

git add config/
git commit -m "add all files in config directory"

Здесь вы успешно сломали свою последнюю фиксацию на две фиксации.

ответ дан przbadu 22 янв. '14 в 11:57
источник
73
голосов

В этом вопросе есть много ответов, но ни один из них не объясняет в деталях, как изменить старые сообщения фиксации с помощью VIM. Я застрял, пытаясь сделать это сам, поэтому здесь я подробно расскажу, как я сделал это специально для людей, которые не имеют опыта работы в VIM!

Я хотел изменить мои пять последних коммитов, которые я уже нажал на сервер. Это довольно "опасно", если кто-то еще вытащил из этого, вы можете повредить вещи, изменив сообщения фиксации. Однако, когда вы работаете над своей маленькой веткой и уверены, что никто ее не потянул, вы можете ее изменить следующим образом:

Предположим, вы хотите изменить свои пять последних коммитов, затем введите это в терминал:

git rebase -i HEAD~5 * Где 5 - количество сообщений фиксации, которые вы хотите изменить. (поэтому, если вы хотите изменить 10-го на последнее коммит, введите 10)

Эта команда приведет вас в VIM там, где вы сможете редактировать свою историю фиксации. Вы увидите последние 5 коммитов вверху:

pick <commit hash> commit message

Вместо pick вам нужно написать reword. Вы можете сделать это в VIM, набрав i, что заставляет вас войти в режим INSERT. (Вы видите, что вы находитесь в режиме вставки с помощью слова INSERT внизу). Для коммитов вы хотите изменить тип в reword вместо pick

Затем вам нужно сохранить и выйти из этого экрана, вы делаете это, сначала перейдя в "командный режим", нажав кнопку esc. (вы можете проверить, что вы в командном режиме, если слово INSERT внизу исчезло). Затем вы можете ввести команду, набрав :, команда сохранения и выхода - wq. Поэтому, если вы наберете :wq youre ont, он будет прав.

Затем VIM перейдет к любому сообщению фиксации, которое вы хотите переписать, здесь вы можете фактически изменить сообщения фиксации. Вы сделаете это, перейдя в режим INSERT, изменив сообщение фиксации, перейдя в командный режим и сохраните и закройте. Сделайте это 5 раз, а вы вне VIM!

Затем, если вы уже подтолкнули свои неправильные коммиты, вам нужно git push --force перезаписать их. Помните, что git push --force - довольно опасная вещь, поэтому убедитесь, что никто не вытащил с сервера, так как вы нажали свои неправильные коммиты!

Теперь вы изменили свои сообщения фиксации!

(Как вы видите, я не настолько опытен в VIM, поэтому, если я использовал неправильный "жаргон", чтобы объяснить, что происходит, не стесняйтесь меня исправлять!)

ответ дан Marijn 07 авг. '14 в 12:18
источник
69
голосов

Я добавил псевдоним reci, recm для recommit (amend) it, теперь я могу сделать это с помощью git recm или git recm -m.

$ vim ~/.gitconfig

[alias]

    ......
    cm = commit
    reci = commit --amend
    recm = commit --amend
    ......
ответ дан Chu-Siang Lai 06 янв. '14 в 10:24
источник
60
голосов

Вы можете использовать git-rebase-reword

Он предназначен для редактирования любой фиксации (не только последней), так же как commit --amend

$ git rebase-reword <commit-or-refname>

Он назван в честь действия по интерактивной переадресации, чтобы исправить фиксацию: "изменить". См. этот пост и man - интерактивный интерактивный режим -

Примеры:

$ git rebase-reword b68f560
$ git rebase-reword HEAD^
ответ дан albfan 21 февр. '15 в 15:21
источник
49
голосов

Я понял, что я нажал на фиксацию с опечаткой. Чтобы отменить, я сделал следующее:

git commit --amend -m "T-1000, advanced prototype"
git push --force

Предупреждение: принудительное нажатие ваших изменений перезапишет удаленную ветку локальным. Убедитесь, что вы не будете переписывать все, что хотите. Также будьте осторожны в силе, надавливающей исправленную (переписанную) фиксацию, если кто-то другой разделяет эту ветку с вами, потому что они должны будут переписать свою собственную историю, если у них есть старая копия коммитов, которую вы только что переписали.

ответ дан neoneye 19 июля '14 в 20:27
источник
42
голосов

Мне нравится использовать следующее:

  • git status
  • git add --all
  • git commit -am "message goes here about the change"
  • git pull <origin master>
  • git push <origin master>
ответ дан Kedar Adhikari 08 сент. '14 в 12:14
источник
37
голосов

Если вы не нажали код на удаленную ветку (GitHub/Bitbucket) вы можете изменить сообщение фиксации в командной строке, как показано ниже.

 git commit --amend -m "Your new message"

Если вы работаете с определенной веткой, выполните следующее:

git commit --amend -m "BRANCH-NAME: new message"

Если вы уже нажали на код с неправильным сообщением, и вам нужно быть осторожным при изменении сообщения. То есть, после того, как вы измените сообщение фиксации и попробуйте нажать его снова, у вас возникнут проблемы. Чтобы сделать его гладким, выполните следующие действия.

Пожалуйста, прочтите мой весь ответ, прежде чем делать это.

git commit --amend -m "BRANCH-NAME : your new message"

git push -f origin BRANCH-NAME                # Not a best practice. Read below why?

Важное примечание:. Когда вы используете принудительное нажатие, вы можете столкнуться с проблемами кода, которые другие разработчики работают над одной ветвью. Чтобы избежать этих конфликтов, вам нужно вытащить код из своей ветки, прежде чем нажимать force:

 git commit --amend -m "BRANCH-NAME : your new message"
 git pull origin BRANCH-NAME
 git push -f origin BRANCH-NAME

Это наилучшая практика при изменении сообщения фиксации, если оно уже было нажато.

ответ дан Packer 13 янв. '15 в 10:03
источник

Другие вопросы по меткам