We had a really bizarre incident at work yesterday. I performed some changes to a repository, committed, and invoked git push, just like I always do. Here's what happened:
user@host:~/path/to/repo$ git add file_a.h
user@host:~/path/to/repo$ git add file_b.h
user@host:~/path/to/repo$ git add file_c
user@host:~/path/to/repo$ git add file_d.h
user@host:~/path/to/repo$ git commit
[master a9c4595] Perform change requested by customer.
4 files changed, 4 insertions(+), 4 deletions(-)
user@host:~/path/to/repo$ git push
Enumerating objects: 17, done.
Counting objects: 100% (17/17), done.
Delta compression using up to 4 threads
Compressing objects: 100% (9/9), done.
Writing objects: 100% (9/9), 845 bytes | 845.00 KiB/s, done.
Total 9 (delta 8), reused 0 (delta 0)
To ssh://git.corp.com:port/project/repo.git
+ 38a09ed...a9c4595 master -> master (forced update)
+ 38a09ed...a9c4595 38 -> 38 (forced update)
user@host:~/path/to/repo$ git log
Specifically observe that (forced update) notice there. My coworker had pushed changes to this repository just before me, and in my ~7 years of Git usage, every single time this scenario has happened, Git has warned me that the remote has changes I don't have, and asks me to pull before I push. Why did this not happen now? Git instead erased my coworker's commit on the remote, and replaced it with my own HEAD^. How would I go about preventing this in the future?
Additional details: Our Git workflow, in terms of integration with other projects, relies on tags, so we have a post-commit hook that looks like this:
#!/bin/bash
tag_ver="$(git describe --tags --match 0 | cut -d'-' -f2)"
git rev-list HEAD | head -n1 | xargs git tag $tag_ver
So every time a commit is made, it just increments the tag by one.