You should think of a pushed master
as being sacred (unless you're the only one editing it). Otherwise, if you start reordering master, (ie you go back in time, change commits, and "force push" them), then you are effectively re-writing history. Anyone else who has pulled master will then have inconsistencies when they pull again, and have to sort them out. Total pain.
There are a few different approaches to keeping a 'nice master', depending on your preference / who you're working with.
The following is how I'd recommend dealing with your situation in these cases:
Linear Master
My preference is a linear master - so this would mean that whenever anyone pushes, they first rebase on top of master, and then push. Master is then a straight line, and you don't get lots of branch merges confusing things.
What you should do is simply add a commit fixing the file at the end of your master, and push that, identifying in the commit message which previous commit you're modifying etc.
That is, you do something along the lines of:
git checkout master
git add FILE_TO_CHANGE
git commit -m 'Bug fix for f95ecfe (Plus more details, obviously)'
git push origin master
(Optionally, create a bug fix branch to work off, then delete it later, a full workflow might look something like):
git pull --rebase origin master //Pull latest code
git checkout master // Move head to master (and check it out)
git checkout -b bug_fix // Create branch and check out to it (currently pointing to the same commit as master)
// Do some work...
git add FILE_TO_CHANGE
git commit -m 'Bug fix for f95ecfe (Plus more details, obviously)'
git pull --rebase origin master // Pull latest code, try to rebase on top of it
git checkout master
git merge bug_fix // fast-forward merge master onto bug_fix branch
git push origin master // push master
git branch -d bug_fix // delete the temporary local branch
Branched master
A branched master allows you to see more clearly which commits are related, but means it can look pretty messy. Some people prefer this approach though.
The work flow would then be something like:
git pull origin master
git checkout f95ecfe // Move head to f95ecfe (note: HEAD is no longer on a branch! - just a commit)
git checkout -b bug_fix // Create branch at the current position and check out to it (branch is pointing to f95ecfe)
// Do some work...
git add FILE_TO_CHANGE
git commit -m 'Bug fix for f95ecfe (Plus more details, obviously)'
git pull origin master // Pull latest code. ALSO merges onto master.
// Alternatively could do:
git merge master
git checkout master // Now we need to bring master up to where we are
git merge bug_fix // fast-forward master onto the bug_fix merge
git push origin master // push master
git branch -d bug_fix // delete the temporary local branch
If you really do want to go back in time and force master
If only you edit master and you want to go back in time and change the commit, and change it on master, do the following:
git checkout f95ecfe
git checkout -b 'bug_fix' // It's nicer to have your head attached to a branch. So create a branch at this point
// Make some changes
git commit --amend 'Message'
Now you need to add all the other commits onto where you currently are. There are quite a few ways of doing this. Personally, I prefer to use the cherry-pick
command through git gui to do this step by step, instead of doing one massive rebase. But the cleanest thing to do is a rebase of master
onto bug_fix
as follows:
git checkout master
git rebase --onto bug_fix f95ecfe // Put the commits from (but not including) f95ecfe up to master, on top of bug_fix
You should then check everything looks like it aught to in git gui, and then you can push:
git push -f origin master
NOTE: As stated before, this is a FORCED push with -f
. Don't do this if anyone else has a copy of the master branch on their machine, as it will make their copy inconsistent, and cause them much misery as they have to rebase all their changes and fix their local master.
PS: There are many ways of doing this section, I give the way I think is most simple (in the sense that it uses more basic commands). Alternatives include making a commit on top of master (as per the linear master instructions) and then using git rebase -i
(interactive mode) to re-order the commits <- this is perhaps the most natural way to do it.