2

tl;dr: Committing something, pushing that, amending that commit and trying to push again without using --force fails. How to set up Git so that it tells, when I try changing 'published commits'?


I am using Git for quite some time now and it still is one of the best things which ever happened to me (software-wise): it totally supports the way I do stuff out of the box. Just yesterday I did something stupid: I committed some stuff, pushed it to my remote, left the work for some minutes and when I came back, I noticed that I changed one of the files after I had added it, so that the commit was not complete. As usual, I used git commit --amend to fix this minor problem.

I worked on for several hours and decided that it was time for another git push. To my dismay, git refused to that and reading the message, scrolling back some thousand lines I saw what I did and knew what was going on. The remote basically is nothing more than a private off-site backup and nobody else uses it to push or pull. So I did not run into trouble with anybody rewriting history using git push --force. Since I would not like this to happen in a multi-user environment (either clean up my history or force-push) I thought about how to prevent this in future: Git could just issue a clearly visible warning, maybe even requiring me to type something. I'd notice and probably decide against amending.

So, the question is: how can I configure Git to warn me about amending commits which have already been pushed? Or more generally: how can I configure Git to warn me about changing published history?

Edit #1 (~6 h later): Unfortunately, I do not feel confident enough to try to implement this on my own, but maybe it helps somebody to help me :) I thought that since --amend affects the latest commit only, it would suffice to have a pre-commit hook that checks the hash of the commit I am trying to amend and the current/latest commit pushed to the remote. For example currently I get b45025a... as the latest commit to master on my local machine, I pushed that and cat .git/refs/remotes/<remote-name>/master gives b45025a... as well. So, would it work to check if the corresponding remote branch is at the same commit as the one I am trying to amend right now?


Before writing this I asked Google and also briefly looked over questions I found here, but nothing seems to fit (selection):

Community
  • 1
  • 1
Kreuvf
  • 273
  • 3
  • 6

1 Answers1

0

You should be able to do this with a post-rewrite git-hook. This gets a list of rewritten commits on stdin which you could check against your remotes. Unfortunately this would just give you an error as there's no pre-rewrite hook.

edit: Someone challenged me to dust off my bash and give this one a try so here's a working warning:

#!/bin/sh
#
# Place this in the file .git/hooks/post-rewrite and make executable
#
# An attempt to write a git-hook to warn of rewritten commits on remotes

while read -r commit junk; do
  if [ ! -z "$(git branch -r --contains $commit)" ]; then
    echo "############################### WARNING ###############################"
    echo "$commit has been rebased but exists on these remote branches"
    echo $(git branch -r --contains $commit)
    echo "You may want to rethink this rewrite"
  fi
done
piemonkey
  • 741
  • 3
  • 6
  • Since I am concerned with amending (and that only applies to the last commit, right?), wouldn't a pre-commit hook might work? I added some more thoughts to the question. Thank you for your efforts! :D – Kreuvf Oct 20 '15 at 21:51
  • From git-scm.com "This hook is invoked by commands that rewrite commits (git commit --amend, git-rebase; currently git-filter-branch does not call it!)". So this hook will catch amends and warn you. If you want to abort the commit you would indeed need to do a pre-commit hook and to do `exit -1` if you can figure a way to detect it. – piemonkey Oct 20 '15 at 22:22
  • Also you can test whether the latest commit exists on a remote branch with `git branch -r --contains $(git show --no-patch --format=%H HEAD)` but the difficulty is figuring out what operation you're currently doing as this on its own catches regular commits as well as amends. – piemonkey Oct 20 '15 at 22:48