unsafe_where_true
unsafe_where_true

Reputation: 6300

Rebase and then force-push lost my changes

We have a policy to not bloat commit history, as it is a big project. So what I usually do, is on my feature branch, I push -f origin featbranch daily, and when finished, I issue a PR.

This approach left me damaged today.

I finished my work on my featbranch. After running all tests etc. successfully, I did a first push -f origin featbranch. origin is my own clone of the repo we work, upstream being the one the PR is issued to.

Then I recalled that upstream/master may have changed already, so in order to keep my featbranch up-to-date, I wanted to rebase:

git fetch upstream master
git rebase upstream/master
git push -f origin featbranch

No errors. I assumed all was ok (I had just double-checked all tests etc....), but to may horrific dismay, I now realize that all my latest changes are lost.

I am left with a strange situation now, and I don't know what happened. In fact it looks like I am left with the very first commit on featbranch: there is a file in featbranch which is definitely not in upstream/master. So I am baffled and don't know what happened here, github says the commit in that branch is from 13 days ago when I actually pushed yesterday.

I guess, due to the -f origin featbranch, that my latest commit can't be recovered - not locally, not on github. I will ignore the policy above from now on and always do daily pushes but without forcing. Nevertheless I would like to understand what happened here.

Upvotes: 0

Views: 999

Answers (3)

Mark Adelsberger
Mark Adelsberger

Reputation: 45659

As you may have learned the hard way here, workflows that make routine use of push -f are dangerous. That push -f doesn't give errors does not mean the operation was safe. Never use force-pushing without understainding the risks and other implications.

However, you may not be as lost as you think.

I don't see anything in the procedure you published that would cause the symptom you describe. I suspect some step was taken that isn't clearly spelled out here. But either way, force pushing doesn't modify your local state. You can still use the reflogs to try to recover your work.

git reflog featbranch

This will show you a history of the featbranch ref, which does two things for you:

First, each time the ref moves, the resulting reflog entry records why it moved; so maybe you can see what actually caused the apparent loss of work.

Second, the ref log also records "before and after" commit ID for each time the ref moved - which means you can recover any previous state as long as it hasn't rolled off the log. In fact the reflog gives a convenient name to each previous state of the ref

git checkout featbranch@{3}

says to go to featbranch as it looked before the 3 most recent changes. The reflog command will tell you the names associated with each such state.

Upvotes: 4

maarten
maarten

Reputation: 492

git has methods for recovering lost commits: git reflog

Furthermore, as you have gathered yourself, the -f option of git push should not be part of your normal workflow. If you want to keep the commit history clean, consider doing it like this.

Upvotes: 2

Paul Sweeney
Paul Sweeney

Reputation: 156

Use

git reflog

to find the state you want to get back to.

See e.g. https://stackoverflow.com/a/1270608/2738122

Upvotes: 2

Related Questions