Исправление git истории двойного фиксации
Мне нужно было запустить git filter-branch
на днях. Я выполнил инструкции в github, но что-то пошло не так. Я думаю, что кто-то из команды не использовал rebase в локальном филиале и вместо этого объединил изменения. С тех пор журнал фиксации заполняется двойными коммитами, например:
commit b0c03ec925c0b97150594a99861d8f21fd3ab22d
Author: XXX
Date: Wed Mar 19 17:01:52 2014 -0400
Removed most clearfixs in templates
commit f30c21d21b5ea715a99b0844793cb4b5f5df97a1
Author: XXX
Date: Wed Mar 19 17:01:52 2014 -0400
Removed most clearfixs in templates
commit 2346be43d0e02d3987331f0a9eeb2f12cd698ede
Author: XXX
Date: Wed Mar 19 16:40:26 2014 -0400
new redirect logic
commit 1383070b31bde1aaa9eda7c2a9bcb598dd72247b
Merge: d1e2eb6 94e07fe
Author: XXX
Date: Wed Mar 19 16:28:41 2014 -0400
Merge branch 'develop' of github.com:xxx/xxx into develop
commit 79ce7824688cf2a71efd9ff82e3c7a71d53af229
Merge: 6079061 1ed3967
Author: XXX
Date: Wed Mar 19 16:28:41 2014 -0400
Merge branch 'develop' of github.com:xxx/xxx into develop
commit d1e2eb645a4fe2a1b3986082d0409b4075a0dbc9
Author: XXX
Date: Wed Mar 19 16:28:36 2014 -0400
Fixed broken responsiveness for companies listing page and code refactoring.
commit 6079061f6ef1f856f94d92bc0fdacf18854b8a89
Author: XXX
Date: Wed Mar 19 16:28:36 2014 -0400
Fixed broken responsiveness for companies listing page and code refactoring.
Как ни странно, не все коммиты удваиваются, например, "новая логика перенаправления" выше. Есть ли что-нибудь, что я могу сделать, чтобы исправить это? Это относительно мягко, но теперь наша история фиксации выглядит как дерьмо. Этот SO post предложил оставить его как есть, но я предпочел бы иметь чистую историю фиксации для потомков.
Ответы
Ответ 1
Команда для выполнения:
git rebase -i HEAD~7
Это откроет ваш редактор примерно так:
pick f392171 Removed most clearfixs in templates
pick ba9dd9a Removed most clearfixs in templates
pick df71a27 Unew redirect logic
pick 79ce782 Merge branch 'develop' of github.com:xxx/xxx into develop
pick 1383070 Merge branch 'develop' of github.com:xxx/xxx into develop
...
Теперь вы можете сказать git, что делать с каждой фиксацией. Пусть сохранится фиксация f392171, та, где мы добавили нашу функцию. Мы раздавим следующие два коммита в первый, оставив нас с одним чистым.
Измените файл следующим образом:
pick f392171 Removed most clearfixs in templates
squash ba9dd9a Removed most clearfixs in templates
pick df71a27 Unew redirect logic
pick 79ce782 Merge branch 'develop' of github.com:xxx/xxx into develop
squash 1383070 Merge branch 'develop' of github.com:xxx/xxx into develop
Когда вы сохраняете и выходите из редактора, git применяет все два изменения, а затем возвращает вас обратно в редактор, чтобы объединить три сообщения фиксации:
# This is a combination of commits.
# The first commit message is:
Removed most clearfixs in templates
# This is the 2nd commit message:
Removed most clearfixs in templates
По завершении сохраните и закройте редактор. git теперь выдаст коммит в один. Все сделано!
Затем вам нужно сделать
git push origin your-branch -f
чтобы принудительно вносить изменения локально в удаленную ветвь.
Примечание. Вы должны делать сквош для каждого дублированного фиксации.
Ответ 2
Ответа на этот вопрос @VAIRIX замечательно, но существуют сложные случаи, когда дублирующие коммиты не отображаются рядом друг с другом, поэтому раздавить не поможет.
Итак, беря ниже истории, (предположим, что ~ является дубликатом a)
# h
# g
# f
# c~
# b~
# a~
# e
# d
# c
# b
# a
Команда, которой следует следовать: (как сказано в ответе @VAIRIX или ниже, если вы хотите переустановить с помощью мастера)
git rebase master -i
(лучше избегать git rebase -i HEAD~n
, чтобы избежать переустановления головной боли)
Теперь!
1) раздавить повторные фиксации, как показано ниже:
pick h
pick g
pick f
pick c~
s b~
s a~
pick e
pick d
pick c
pick b
pick a
Теперь это будет выдавливать ваши коммиты в c
# h
# g
# f
# c~ (having changes of a~ and b~)
# e
# d
# c
# b
# a
В моем случае c ~ была анти-фиксацией c, поэтому мне просто нужно было выполнить этот процесс еще раз, но теперь вместо squash с s
я отбрасываю фиксацию с помощью d
pick h
pick g
pick f
d c~ (having changes of a~ and b~)
pick e
pick d
pick c
pick b
pick a
Теперь вы будете удалять все дубликаты. Теперь вы можете сравнить с веткой происхождения, с которой вы использовали git diff
, который дублировал вашу ветку. Не должно быть никакого различия, если вы сделали это отлично.
Этот процесс может показаться немного длиннее, но вы уверены, что не пропустили никаких коммитов.