403

There's ways to change the message from later commits:

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

How can you change the commit message of the very first commit (which has no parent)?

Martin G
  • 17,357
  • 9
  • 82
  • 98
13ren
  • 11,887
  • 9
  • 47
  • 64

5 Answers5

686

As of Git version 1.7.12, you may now use

git rebase -i --root

Documentation

ParaBolt
  • 1,593
  • 2
  • 10
  • 16
ecdpalma
  • 10,662
  • 3
  • 21
  • 24
  • 2
    is it possible to rebase the root of all branches using this command? Seems like this will detach the current branch onto the new root and all the other branches will stay on the old root – woojoo666 Mar 22 '15 at 07:29
  • @woojoo666 you will have to rebase branches onto new root then. as usual. – berkus Apr 24 '15 at 12:13
  • @Atcold it doesn't work if there is no upstream root – Kai May 20 '16 at 05:31
  • Warning: I wrongly assumed this would do the root of my checked out branch, but it takes a while to load all the commits, then rebase them all. – Leo May 25 '16 at 17:44
  • 2
    FWIW: I would also like to see this as the accepted answer, especially as it matches my all-time favourite `git` command for cleaning up the history of new projects in the early stages of development, namely: `git rebase --interactive --autosquash --autostash --root` – pvandenberk Jun 13 '16 at 08:56
  • 2
    @Leo what does your comment mean? I can't see the link between the first part and the second - what does taking a while have to do with it? – boycy Nov 29 '17 at 12:29
320

Assuming that you have a clean working tree, you can do the following.

# 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
Zombo
  • 1
  • 62
  • 391
  • 407
CB Bailey
  • 755,051
  • 104
  • 632
  • 656
  • 28
    I believe this should be `git rebase --onto HEAD master`. – Andrew May 09 '12 at 20:58
  • 1
    @Andrew: In this example `HEAD` _is_ the amended root commit. – CB Bailey May 09 '12 at 21:07
  • 5
    Right, but you want the _original_ root commit for the of `git rebase`. `git rebase` applies commits in (`master`) that are not in ; `HEAD` is not in `master`, so your version tries to apply all of `master`. – Andrew May 16 '12 at 18:41
  • 8
    Yes, make sure it's `git rebase --onto HEAD ` master, where `` is the same used in `git checkout `. Otherwise, you'll have 2 `first commit`'s. – Andy Jun 18 '12 at 19:01
  • 1
    if the first commit was made with _--allow-empty_ is needed to use _git commit --ammend --allow-empty_. Rest is the same – albfan Oct 13 '12 at 08:47
  • 1
    @VonC you want to see another crazy usage of `--onto`, along with `--root`? Check out [my answer](http://stackoverflow.com/a/16764517/456814) to [Git: how to add commits before first (root) commit?](http://stackoverflow.com/questions/16762160/git-how-to-add-commits-before-first-root-commit)! –  Jul 14 '13 at 21:55
  • 3
    @Cupcake: Did you test the old version of the command? It should work fine. The amend is changing the commit message only so the old and new root commits introduce exactly the same changes so the old root commit is skipped automatically. The second `HEAD` ensures that all commits are considered and that we can use the two parameter version of rebase to move back onto master. Please note that this answer predates the existence of the `--root` option to rebase. – CB Bailey Jul 15 '13 at 07:06
  • @VonC (and all) I don't see why you need --onto ,I've omitted and it works just fine (well seemed to), I thought --onto was only necessary if it didn't match the commit (which it does in this case)? – sabgenton Nov 28 '13 at 16:41
  • 1
    @sabgenton if you omit it, it should be a no-op (ie rebase but don't do much). You can also use the `git rebase -i --root` mentioned below (no --onto there). – VonC Nov 28 '13 at 16:44
  • @VonC but it did work I changed the base commit message and rebased all the above commits.... are you referring to an older git? It was git 1.7.1 . The rebase did happen. So can we say if it works, fine if it no-ops then use --onto ? – sabgenton Nov 28 '13 at 17:13
  • @VonC the man says `If the --onto option is not specified, the starting point is ` that means `git rebase HEAD master` is the same as `git rebase --onto HEAD HEAD master` and it works for me! – sabgenton Dec 16 '13 at 08:28
  • @sabgenton that makes sense. Let's wait Charles's opinion on that. – VonC Dec 16 '13 at 08:30
  • Reading the docs, it does sound like that should be the same but I haven't tested it. I'd prefer to test before changing the answer. – CB Bailey Dec 16 '13 at 08:37
  • I've tried it from 1.7.1 up and it works. On the good side --onto makes more sense to me now after researching it after this answer. – sabgenton Dec 16 '13 at 20:54
  • Be interested to hear your results :) – sabgenton Dec 16 '13 at 20:56
  • @CharlesBailey excellent answer btw, most long term support servers are not on 1.7.12 yet! – sabgenton Dec 18 '13 at 23:27
  • I got a corrected commit message, but now I get the old and new commits when I do git log. Also when I pushed it I had to do a pull and merge and then push. I wanted ONLY to change my first commit message, all the rest should have stayed EXACTLY the same. – powder366 Mar 09 '14 at 11:05
  • 1
    @powder366: well, if you merged the old and the new histories then you will get both as the ancestors of your updated master branch. You would have had to use a forced or non-fastfoward push (if allowed by your server) to _replace_ the history. – CB Bailey Mar 09 '14 at 11:16
  • 11
    [ecdpalma's answer](http://stackoverflow.com/a/14630424/247696) below is much easier and simpler and has more votes, scroll down people! – Flimm Oct 02 '15 at 13:37
  • Worked like a charm for me – Houssam Badri Feb 11 '19 at 06:59
  • You want to rebase onto `HEAD` (the new root commit), from `HEAD@{1}` (the previous position of HEAD) to `master`. Use the command `git rebase --onto HEAD HEAD@{1} master` It is then easy to rebase branches onto others, e.g. if `branch2` is after `branch1` and `branch1` after `master`, you can do `git rebase --onto upstream/master master branch1` followed by `git rebase --onto branch1 branch1@{1} branch2` – madprog Feb 21 '19 at 20:57
73

To expand on ecdpalma's answer, you can now use the --root option to tell rebase that you want to rewrite the root/first commit:

git rebase --interactive --root

Then the root commit will show up in the rebase TODO list, and you can select to edit or reword it:

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

This is the explanation of --root from the Git rebase docs (emphasis mine):

Rebase all commits reachable from <branch>, instead of limiting them with an <upstream>. This allows you to rebase the root commit(s) on a branch.

Community
  • 1
  • 1
16

Just to provide an alternative to the higher rated answers:

If you are creating a repo, and know upfront that you'll be rebasing on top of its "first" real commit in the future, you can avoid this problem altogether by making an explicit empty commit at the beginning:

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

and only then start doing "real" commits. Then you can easily rebase on top of that commit the standard way, for example git rebase -i HEAD^

jakub.g
  • 38,512
  • 12
  • 92
  • 130
  • 7
    Doesn't this mean that, in order for this to work, you need to have the foresight (or be psychic) to make an empty commit *right at the very beginning of your project*? This seems to be ***extremely situational***, to me, and generally ***not practical***. What do you think? What happens if I've already made 100 commits, and I suddenly need to edit the root commit. Will this still work, in that case, if I didn't make that empty commit at the start? –  Jul 20 '14 at 06:58
  • 4
    Editing the message of the root commit is probably not something you would do after having 100s of them. I sometimes happen to just want to have a git repo, doing some trashy commits, knowing that once I reach some usable state, I'd squash them into one for instance, and reword the message. Anyway, now I changed my mind and I think the absolutely most useful thing for the first commit would be putting `.gitattributes` file instead of doing an empty commit. – jakub.g Jul 20 '14 at 23:51
  • Reply to the first commenter: You don’t have to have the foresight to make an empty commit every time. You could (1) create a repository with this empty commit (2) place it in some “git repository templates” directory (3) copy it over whenever you need a new repository. – Guildenstern May 01 '23 at 08:23
4

You could use 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
Alexander Groß
  • 10,200
  • 1
  • 30
  • 33
  • I'm using filter-branch change the author / committer, and the `-- --all` option indeed is the key in this case to be able to also handle the root commit. – sschuberth Feb 06 '14 at 08:04