Редактировать корневой коммит в Git?

328

Есть способы изменить сообщение из последующих коммитов:

git commit --amend                    # for the most recent commit
git rebase --interactive master~2     # but requires *parent*

Как вы можете изменить сообщение коммита самого первого коммита (у которого нет родителя)?

13ren
источник
В частности: использование переменной окружения GIT_COMMIT в скриптеgit filter-branch --msg-filter
fork0
1
см. также stackoverflow.com/a/2309391/264607
BlackICE

Ответы:

284

Предполагая, что у вас чистое рабочее дерево, вы можете сделать следующее.

# checkout the root commit
git checkout <sha1-of-root>

# amend the commit
git commit --amend

# rebase all the other commits in master onto the amended root
git rebase --onto HEAD HEAD master
CB Bailey
источник
23
Я считаю, что это должно быть git rebase --onto HEAD <sha1-of-root> master.
Андрей
5
Правильно, но вы хотите оригинальный корневой коммит для <upstream> of git rebase. git rebaseприменяет коммиты в <branch> ( master), которых нет в <upstream>; HEADне в master, так что ваша версия пытается применить все master.
Андрей
7
Да, убедитесь, что это git rebase --onto HEAD <sha1-of-root>мастер, где <sha1-of-root>используется то же самое git checkout <sha1-of-root>. В противном случае у вас будет 2 first commit.
Энди
2
@Cupcake: вы тестировали старую версию команды? Это должно работать нормально. Поправка изменяет только сообщение фиксации, поэтому старые и новые корневые коммиты вносят точно такие же изменения, поэтому старый корневой коммит автоматически пропускается. Второй HEADгарантирует, что все коммиты будут учтены, и что мы сможем использовать двухпараметрическую версию rebase, чтобы вернуться на master. Обратите внимание, что этот ответ предшествует существованию --rootопции перебазирования.
CB Bailey
9
Ответ ecdpalma, приведенный ниже, намного проще и проще и имеет больше голосов, прокрутите вниз людей!
Flimm
567

Начиная с Git версии 1.7.12 , теперь вы можете использовать

git rebase -i --root

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

ecdpalma
источник
2
Можно ли перебазировать корень всех веток с помощью этой команды? Похоже, это отсоединит текущую ветку от нового корня, а все остальные ветви останутся на старом корне
woojoo666
@ woojoo666 тогда вам придется перебазировать ветки на новый корень. по-прежнему.
berkus
@ Уточните, это не сработает, если нет восходящего корня
Kai
Предупреждение: я ошибочно предположил, что это сделает корень моей извлеченной ветки, но это требует времени, чтобы загрузить все коммиты, а затем перебазировать их все.
Лев
2
@ Лео, что означает твой комментарий? Я не вижу связи между первой частью и второй - что общего с этим связано?
мальчик
66

Чтобы расширить ответ ecdpalma , теперь вы можете использовать --rootопцию, чтобы сказать, rebaseчто вы хотите переписать root / first commit:

git rebase --interactive --root

Тогда корневой коммит появится в списке перебазирования TODO, и вы можете выбрать его для редактирования или перефразирования:

reword <root commit sha> <original message>
pick <other commit sha> <message>
...

Это объяснение --rootиз документации по Git rebase (выделено мной):

Перебазируйте все коммиты, доступные из <branch>, вместо того, чтобы ограничивать их с помощью <upstream>. Это позволяет вам перебазировать корневой коммит (ы) на ветке .

Сообщество
источник
12

Просто чтобы предоставить альтернативу более высоким рейтингам ответов:

Если вы создаете репо и заранее знаете, что в будущем вы будете перебазировать его «первый» реальный коммит, вы можете полностью избежать этой проблемы, сделав вначале явный пустой коммит:

git commit --allow-empty -m "Initial commit"

и только тогда начинайте делать "настоящие" коммиты. Затем вы можете легко перебазировать поверх этого коммита стандартным способом, напримерgit rebase -i HEAD^

jakub.g
источник
4
Не означает ли это, что для того, чтобы это сработало, вам нужно иметь предвидение (или быть экстрасенсом), чтобы сделать пустой коммит в самом начале вашего проекта ? Это кажется чрезвычайно ситуативнымМне и вообще не практично . Что вы думаете? Что произойдет, если я уже сделал 100 коммитов, и мне вдруг нужно отредактировать корневой коммит. Будет ли это работать, если я не сделаю этот пустой коммит в начале?
2
Редактирование сообщения корневого коммита, вероятно, не то, что вы сделали бы после сотен из них. Иногда мне просто хочется иметь git-репо, делать какие-то дрянные коммиты, зная, что, когда я достигну некоторого пригодного для использования состояния, я, например, раздавлю их в одно и перефразирую сообщение. Как бы то ни было, теперь я передумал и думаю, что самым полезным для первого коммита было бы.gitattributes файл вместо пустого.
jakub.g
4

Вы можете использовать git filter-branch:

cd test
git init

touch initial
git add -A
git commit -m "Initial commit"

touch a
git add -A
git commit -m "a"

touch b
git add -A
git commit -m "b"

git log

-->
8e6b49e... b
945e92a... a
72fc158... Initial commit

git filter-branch --msg-filter \
"sed \"s|^Initial commit|New initial commit|g\"" -- --all

git log
-->
c5988ea... b
e0331fd... a
51995f1... New initial commit
Александр Грос
источник
Я использую фильтр-ветку для изменения автора / коммиттера, и -- --allв этом случае опция действительно является ключом, чтобы можно было также обрабатывать корневой коммит.
sschuberth