DON'T PANIC. It can all be restored.
Above all do not do any more pushes without first understanding exactly what they're doing. Perhaps wait until Monday for your colleagues to return.
You never should have been able to push without --force. Something else happened. Let's graph this out.
I have been working on a branch for a project that was 100+ commits ahead of master. A colleague pushed some changes to master in the past few days, and I never pulled the new changes onto my local environment.
Let's call it 3 commits ahead. Your local repo looks like this.
[origin/master]
A - B - C [master]
\
D - E - F [feature]
And the remote looks like this.
A - B - C - G - H - I [master]
In my haste to get my work deployed, I forgot to pull from origin/master first, and I merged my big branch with my local master...
After that merge, your repo would look like this:
[origin/master]
A - B - C --------- M [master]
\ /
D - E - F [feature]
...and pushed to the remote repository.
You could not have without --force because your local master and origin's master have diverged. It will become more clear if we look at your repo after a git fetch.
G - H - I [origin/master]
/
A - B - C --------- M [master]
\ /
D - E - F [feature]
Your master cannot be applied by simply adding commits to origin/master. git push will not work.
Something is missing here. It could be that...
- You used
git push --force.
- Your colleague never pushed to master.
- ???
Either way, here's how you fix it.
- Get your colleague to
git push --force their master branch.
This restores their version of master.
- If you deleted your branch, recreate it just before the merge.
You'll need it to redo the merge. In the example above that would be git branch feature F.
git fetch
This will update your idea of origin. origin/master should now be on your colleague's work.
$ git fetch
G - H - I [origin/master]
/
A - B - C --------- M [master]
\ /
D - E - F [feature]
- Checkout master and
git reset --hard origin/master.
This will wipe out your local changes to master and restore it to origin/master, effectively undoing the merge. It simply moves your master label to where origin/master is.
$ git checkout master
$ git reset --hard origin/master
[origin/master]
A - B - C - G - H - I [master]
\
D - E - F [feature]
- Redo the merge.
$ git merge feature
[origin/master]
A - B - C - G - H - I - M [master]
\ /
D - E ----- F [feature]
git push.
$ git push
[origin/master]
A - B - C - G - H - I - M [master]
\ /
D - E ----- F [feature]
Once this is all resolved, consider making master a protected branch which cannot be directly pushed to; all changes to master must go through an integration step such as a pull or merge request. GitLab and Github offer protected branches. Or it can be done with hooks.
This avoids goofs, and ensures master is a stable code base to work from.