Search code examples
gitgithooks

Is it possible to edit a Git commit message using the pre-push hook?


Before users push their commits, I'd like to pre-pend the branch name to the commit message. Is this possible?

If it is, would I use the git commit --amend command?

Our branch names contain the ticket number and its important to see this info when its merged into master and in Jenkins. To see it easily, it must be the first line in the commit message. To ensure the fist line is the branch name (containing the ticket number), I'd like to use the pre-push hook. I could use other hooks, such as prepare-commit-message or use a message template but that puts the branch name on every commit, and it doesn't ensure that the branch name is there after a rebase. Using the pre-push ensures the branch name is there before it goes into the remote.

=============

update: Yes, it is possible but its a bad idea.

The pre-push hook syncs the refs with the remote before running but before any objects are pushed. This means the remote already has the commit sha set for the change you are pushing. When the pre-push hook amends the commit message a new sha is generated, putting you immediately out of sync with the remote.


Solution

  • As you've found, the answer is effectively "no". In fact it's truly "no", for a deeper technical reason: it's impossible to edit any commit. What git commit --amend does is not "edit a commit", but rather, shove the commit aside and change the current branch name, whatever that is, to point to the new commit. The "before" picture is:

    ...--o--o--*   <--current_branch (HEAD)
    

    and the "after" one is:

              *   [abandoned - in reflog as HEAD@{1}, etc]
             /
    ...--o--o--X   <--current_branch (HEAD)
    

    But the pre-push hook runs after your Git has already called up the other Git and offered to send it commit * by its hash ID. The fact that you've replaced commit * by new-and-improved commit X is now irrelevant: your Git is dedicated to pushing commit * and asking their Git to set their branch to point to (their copy of) commit *.

    What you can do, in this pre-push hook, is reject the push from your own end. Now that the push is rejected and fails, you can re-run your git push command. This time you'll propose to send them commit X. If it looks right, you won't have any need to run git commit --amend and can leave commit X in place for the push, and let the push run.

    Note that it's far better to do this outside Git. Instead of:

    $ git push remotename HEAD:somebranch
    

    or whatever it is you actually run, you would just run:

    $ jirapush
    

    which is your own script. In this script, you can run whatever Git commands you like, in whatever order, before running git push remotename <hash>:<branchname> or whatever it is that you will run at the very end. Those Git commands can include, e.g.:

    generate_new_commit_message_text | git commit --amend -F -
    

    if necessary. Since it all happens before git push fires up, it's well in time to do whatever it is you want done.