30 lines
2.5 KiB
Markdown
30 lines
2.5 KiB
Markdown
---
|
|
title: "TIL: Recovering from an accidental force push in git"
|
|
date: 2023-03-17T08:07:08
|
|
slug: til-recovering-from-an-accidental-force-push-in-git
|
|
|
|
---
|
|
I don't normally force-push to repos, but I wanted to overwrite the contents of an old project with a new one of the same name. So last night, I created my new project, set the git origin url to the correct one (`git set-url origin git@...`), and then ran `git push -u origin main --force`. After that, I switched off my laptop and went to bed.
|
|
|
|
Then, this morning, I switch on my other machine and pull the project I'm working on aaaand... everything disappears. Oops. I wasn't thinking and set the wrong url in the repo, and force-pushed to the wrong repository. Luckily it was fairly easy to recover from this, and nothing there goes to prod so there were no services with downtime.
|
|
|
|
## Getting back to the correct commit
|
|
|
|
My first instinct was to check `git log`, but because `git push --force` overrides the log, all I saw was the classic "initial commit" message from my new project. However, you can still get the full commit history using [reflog](https://git-scm.com/docs/git-reflog).
|
|
|
|
Running `git reflog show` gave me a full log of every commit, even the ones from before the force-push. I could see after the two commits I'd accidentally pulled (one with my initial commit, one rebasing it onto my local repo), and then under that was the last real commit I made on the project. The entry looked a bit like this:
|
|
|
|

|
|
|
|
So, running `git checkout HEAD@{n}` where `n` was the number in the curly braces let me checkout my original changes in a detached state. Great, all was not lost!
|
|
|
|
## Pushing back to main
|
|
|
|
I didn't really care about the changes I currently had on the repo from the new project - it's just boilerplate setup, and it's still on my other machine anyway. So, to move my currently detached state back to the repo `HEAD`, I doubled down on my mistake and did a second force push: ` git push origin HEAD:main --force`.
|
|
|
|
And that worked! My git commit history is back, the files are visible on the remote repository, all is not lost.
|
|
|
|
## Lesson learned?
|
|
|
|
Eh, maybe? I wouldn't use `push --force` on anything that: a) wasn't owned by me, b) was deploying straight to production/was actually in use. This was just me being overtired and too lazy to delete & remake a repository. I'd probably do it again, which is why I'm writing this.
|