Как изменить более старый Git commit?

Я сделал 3 git совершает, но не был нажат. Как изменить старый (ddc6859af44) и (47175e84c), который не является последним?

$git log
commit f4074f289b8a49250b15a4f25ca4b46017454781
Date:   Tue Jan 10 10:57:27 2012 -0800

commit ddc6859af448b8fd2e86dd0437c47b6014380a7f
Date:   Mon Jan 9 16:29:30 2012 -0800

commit 47175e84c2cb7e47520f7dde824718eae3624550
Date:   Mon Jan 9 13:13:22 2012 -0800

Ответ 1

git rebase -i HEAD^^^

Теперь отметьте те, которые вы хотите изменить, с помощью edit или e (замените pick). Теперь сохраните и выйдите.

Теперь внесите изменения, затем

git add -A
git commit --amend --no-edit
git rebase --continue

Если вы хотите добавить дополнительное удаление, удалите параметры из команды commit. Если вы хотите настроить сообщение, опустите только параметр --no-edit.

Ответ 2

Я подготовил свой коммит, который я хотел внести с более старым, и был удивлен, увидев, что rebase -i жаловался, что у меня есть незафиксированные изменения. Но я не хотел, чтобы мои изменения снова указывали параметр редактирования старшего коммита. Таким образом, решение было довольно простым и понятным:

  • подготовьте свое обновление к старшему, добавьте его и выполните
  • git rebase -i <commit you want to amend>^ - обратите внимание на ^, чтобы вы увидели указанную фиксацию в текстовом редакторе
  • вы получите следующее:

    pick 8c83e24 use substitution instead of separate subsystems file to avoid jgroups.xml and jgroups-e2.xml going out of sync
    pick 799ce28 generate ec2 configuration out of subsystems-ha.xml and subsystems-full-ha.xml to avoid discrepancies
    pick e23d23a fix indentation of jgroups.xml
    
  • Теперь для объединения e23d23a с 8c83e24 вы можете изменить порядок строк и использовать сквош следующим образом:

    pick 8c83e24 use substitution instead of separate subsystems file to avoid jgroups.xml and jgroups-e2.xml going out of sync    
    squash e23d23a fix indentation of jgroups.xml
    pick 799ce28 generate ec2 configuration out of subsystems-ha.xml and subsystems-full-ha.xml to avoid discrepancies
    
  • напишите и выйдите из файла, вы будете вместе с редактором, чтобы объединить сообщения фиксации. Сделайте это и сохраните/выйдите из текстового документа

  • Вы закончили, ваши изменения изменены.

кредит идет на: http://git-scm.com/book/en/Git-Tools-Rewriting-History Там также есть полезная продемонстрированная магия git.

Ответ 3

Вы можете использовать git rebase для перезаписи истории фиксации. Это может быть потенциально разрушительным для ваших изменений, поэтому используйте с осторожностью.

Сначала сделайте свое изменение "изменить" как обычное совершение. Затем выполните интерактивную переадресацию, начиная с родителя вашей старой фиксации

git rebase -i 47175e84c2cb7e47520f7dde824718eae3624550^

Это запустит ваш редактор со всеми фиксациями. Измените порядок, чтобы ваше "исправление" совершалось ниже того, которое вы хотите изменить. Затем замените первое слово в строке на "commit" commit с помощью s, которое объединит ( s quash) его с фиксацией раньше. Сохраните и выйдите из редактора и следуйте инструкциям.

Ответ 4

Вы можете использовать git rebase --interactive, используя команду edit для фиксации, которую вы хотите изменить.

Ответ 5

Я использовал другой способ несколько раз. Фактически, это руководство git rebase -i, и оно полезно, если вы хотите переставить несколько коммитов, включая раздавливание или разделение некоторых из них. Главное преимущество заключается в том, что вам не нужно принимать решение о каждой совершении судьбы в один момент. Вы также будете иметь все функции Git, доступные во время процесса, в отличие от во время переустановки. Например, вы можете в любое время отобразить журнал как исходной, так и перезаписанной истории или даже выполнить другую перезагрузку!

Я буду ссылаться на коммиты следующим образом, поэтому легко читаем:

C # good commit after a bad one
B # bad commit
A # good commit before a bad one

Ваша история в начале выглядит следующим образом:

x - A - B - C
|           |
|           master
|
origin/master

Мы воссоздаем его таким образом:

x - A - B*- C'
|           |
|           master
|
origin/master

Это процедура:

git checkout B       # get working-tree to the state of commit B
git reset --soft A   # tell git that we are working before commit B
git checkout -b rewrite-history   # switch to a new branch for our alternative history

Улучшите свою старую фиксацию с помощью git add (git add -i, git stash и т.д.). Вы можете даже разделить свою старую фиксацию на две или более.

git commit           # recreate commit B (result = B*)
git cherry-pick C    # copy C to our new branch (result = C')

Промежуточный результат:

x - A - B - C 
|    \      |
|     \     master
|      \
|       B*- C'
|           |
|           rewrite-history
|
origin/master

Пусть заканчивается:

git checkout master
git reset --hard rewrite-history  # make this branch master

Чтобы это, вы можете push продвигаться вперед.

Ответ 6

В случае, если OP хочет выжать 2 коммиты, указанные в 1, вот альтернативный способ сделать это без перезагрузки

git checkout HEAD^               # go to the first commit you want squashed
git reset --soft HEAD^           # go to the second one but keep the tree and index the same
git commit --amend -C [email protected]{1}   # use the message from first commit (omit this to change)
git checkout [email protected]{3} -- .       # get the tree from the commit you did not want to touch
git add -A                       # add everything
git commit -C [email protected]{3}           # commit again using the message from that commit

Синтаксис @{N) удобен, так как он позволит вам ссылаться на историю того, где были ваши ссылки. В этом случае это HEAD, который представляет вашу текущую фиксацию.