Let's say you have branches dev
and main
.
Recall that a Git repository is a "graph" of commits, and branches are "pointers" to specific commits in that graph.
Your mistake has resulted in removing a branch pointer from branch foo
, and placed it elsewhere in the commit graph. The commits are still there, but they no longer have a branch pointing to them. Eventually, they will be "garbage collected" and deleted, but they are probably still there.
Your commit graph might look like this before the mistake:
$ git log --graph --oneline --decorate
* 7da3c3 (dev) add
| * cb44c2 (HEAD -> main) update
|/
* c62eda Add a
Then you run git branch -C dev
.
After this mistake, your commit graph might look like this:
$ git log --graph --oneline --decorate
* cb44c2 (HEAD -> dev, main) update
* c62eda Add a
Commit 7da3c3
seems to have disappeared!
Don't panic. The commit is not deleted, it's just no longer visible in the default git log
output, because there's nothing pointing to it.
If you already happen to know that the "lost" branch pointed to 7da3c3
, you could just run git branch -f dev 7da3c3
(or git switch -C dev 7da3c3
) to move the dev
branch pointer back to its original location. But we usually don't know commit hashes off the top of our heads, so we need to figure out what hash we need to move the branch pointer to.
We can view "lost" commits using git log --reflog
, as shown in Get a list of all git commits, including the 'lost' ones:
$ git log --reflog --graph --oneline --decorate
* 7da3c3 add
| * cb44c2 (HEAD -> dev, main) update
|/
* c62eda Add a
Here we can see our old commit 7da3c3
without any branch pointer. Then all we have to do is move the branch pointer back to the right place, using git branch -f dev 7da3c3
as I stated above. The -f
/--force
option is required because git branch
will otherwise refuse to re-create/move a branch that already exists without "force"-ing.
You can also use the git reflog dev
command as shown in the other answer to view the history specifically of the dev
branch, which might be more directly useful, but doesn't provide as nice of a visual overview as log --graph
.
Note also that your reflog output might look a lot busier than in my simple example, if you have performed other branch moves, rebases, etc. Usually git reflog <branch>
should show the correct commit directly at the top of the list, but that won't always be the case in "recovery" operations like this one. You might need to look around for a while in order to find the right one. You may use git show
to view commits by their hash (e.g. git show 7da3c3
), or use git checkout
/git switch --detached
to move around the repository in "detached head" mode.