To move the branch pointer of a checked out branch, one can use the git reset --hard
command. But how to move the branch pointer of a not-checked out branch to point at a different commit (keeping all other stuff like tracked remote branch)?
git branch <branch-name> <SHA-1-of-the-commit>
and dump the old branch?
git branch --force <branch-name> [<new-tip-commit>]
If new-tip-commit
is omitted, it defaults to the current commit.
new-tip-commit
can be a branch name (e.g., master, origin/master).
You can do it for arbitrary refs. This is how to move a branch pointer:
git update-ref -m "reset: Reset <branch> to <new commit>" refs/heads/<branch> <commit>
where -m
adds a message to the reflog for the branch.
The general form is
git update-ref -m "reset: Reset <branch> to <new commit>" <ref> <commit>
You can pick nits about the reflog message if you like - I believe the branch -f
one is different from the reset --hard
one, and this isn't exactly either of them.
git branch -f
. To be specific, this method appears to be: (A) harder to use (B) harder to remember, and (C) more dangerous
You can also pass git reset --hard
a commit reference.
For example:
git checkout branch-name
git reset --hard new-tip-commit
I find I do something like this semi-frequently:
Assuming this history
$ git log --decorate --oneline --graph
* 3daed46 (HEAD, master) New thing I shouldn't have committed to master
* a0d9687 This is the commit that I actually want to be master
# Backup my latest commit to a wip branch
$ git branch wip_doing_stuff
# Ditch that commit on this branch
$ git reset --hard HEAD^
# Now my changes are in a new branch
$ git log --decorate --oneline --graph
* 3daed46 (wip_doing_stuff) New thing I shouldn't have committed to master
* a0d9687 (HEAD, master) This is the commit that I actually want to be master
git update-ref
as discussed above.
git reset --hard ...
No need to repeat it here! :-(
Just to enrich the discussion, if you want to move myBranch
branch to your current commit, just omit the second argument after -f
Example:
git branch -f myBranch
I generally do this when I rebase
while in a Detached HEAD state :)
In gitk --all
:
right click on the commit you want
-> create new branch
enter the name of an existing branch
press return on the dialog that confirms replacing the old branch of that name.
Beware that re-creating instead of modifying the existing branch will lose tracking-branch information. (This is generally not a problem for simple use-cases where there's only one remote and your local branch has the same name as the corresponding branch in the remote. See comments for more details, thanks @mbdevpl for pointing out this downside.)
It would be cool if gitk
had a feature where the dialog box had 3 options: overwrite, modify existing, or cancel.
Even if you're normally a command-line junkie like myself, git gui
and gitk
are quite nicely designed for the subset of git usage they allow. I highly recommend using them for what they're good at (i.e. selectively staging hunks into/out of the index in git gui, and also just committing. (ctrl-s to add a signed-off: line, ctrl-enter to commit.)
gitk
is great for keeping track of a few branches while you sort out your changes into a nice patch series to submit upstream, or anything else where you need to keep track of what you're in the middle of with multiple branches.
I don't even have a graphical file browser open, but I love gitk/git gui.
git status
output is affected. Additionally, in some cases git fetch
and git push
won't work without specifying remote explicitly if you don't set the tracking branch. I don't know about all the cases, but for me the general rule of thumb is that for convenience and speed of work, it's better to have tracking branches in order.
The recommended solution git branch -f branch-pointer-to-move new-pointer
in TortoiseGit:
"Git Show log"
Check "All Branches"
On the line you want the branch pointer to move to (new-pointer): Right click, "Create Branch at this version" Beside "Branch", enter the name of the branch to move (branch-pointer-to-move) Under "Base On", check that the new pointer is correct Check "Force" Ok
Right click, "Create Branch at this version"
Beside "Branch", enter the name of the branch to move (branch-pointer-to-move)
Under "Base On", check that the new pointer is correct
Check "Force"
Ok
https://i.stack.imgur.com/jMZWU.png
https://i.stack.imgur.com/WZhnB.png
Honestly, I'm surprised how nobody thought about the git push
command:
git push -f . <destination>:<branch>
The dot ( . ) refers the local repository, and you may need the -f option because the destination could be "behind its remote counterpart".
Although this command is used to save your changes in your server, the result is exactly the same as if moving the remote branch (<branch>
) to the same commit as the local branch (<destination>
)
-f
to avoid clobbering anything local; for instance, git fetch origin && git push . origin/develop:develop
is a no-checkout-needed fail-fast version of git checkout develop && git pull --ff-only
Git 2.23.0 introduced the git-switch
command that can also be used to do this.
git switch -C <branch-name> [<start-point>]
The -C
(uppercase C) option indicates that if <branch-name>
already exists, it will reset it to <start-point>
.
With -c
(lowercase C) it will try to create a new branch but fails if one already exists.
<start-point>
can be a hash, a tag, or another branch name.
git version 2.35.1
... git switch --help | egrep -i EXPERIMENTAL
said THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE.
git switch
command has been experimental from when it was introduced in version 2.23.0. See this from the Git Blog in August 2019 github.blog/2019-08-16-highlights-from-git-2-23
-c|-C
flag behaviour discussed here has not changed since the command was introduced in August 2019.
If you want to move a non-checked out branch to another commit, the easiest way is running the git branch command with -f option, which determines where the branch HEAD should be pointing to:
git branch -f <branch-name> (<sha1-commit-hash> or <branch-name>)
For example if you want your local develop branch to track the remote (origin) develop branch:
git branch -f develop origin/develop
Be careful as this won't work if the branch you are trying to move is your current branch. To move a branch pointer, run the following command: git update-ref -m "reset: Reset to " refs/heads/
The git update-ref command updates the object name stored in a ref safely.
Hope, my answer helped you.The source of information is this snippet.
Open the file .git/refs/heads/<your_branch_name>
, and change the hash stored there to the one where you want to move the head of your branch. Just edit and save the file with any text editor. Just make sure that the branch to modify is not the current active one.
Disclaimer: Probably not an advisable way to do it, but gets the job done.
git commit
is the most compelling reason to use git instead of mercurial.
For the checked out branch, in the case the commit you want to point to is ahead of the current branch (which should be the case unless you want to undo the last commits of the current branch), you can simply do:
git merge --ff-only <commit>
This makes a softer alternative to git reset --hard
, and will fail if you are not in the case described above.
To do the same thing for a non checked out branch, the equivalent would be:
git push . <commit>:<branch>
git push . <commit>:<branch>
as already suggested.
git merge --ff-only
, and then only if there are no conflicts.
--ff-only
option if you want to be sure, but that option does not alter the way the merge is done, it just prevents non fast forward merges to be done. Also, if the merge is not fast forward, you can refuse the commit and cancel the merge with git merge --abort
.
git merge
would require a few more commands to protect both the starting branch and the working tree. git stash; git checkout <branch>; git merge --ff-only <commit>; git checkout <starting-branch>; git pop
Success story sharing
git update-ref -m "reset: Reset <branch> to <new commit>" <branch> <commit>
. (You can pick nits about the reflog message if you like - I believe thebranch -f
one is different from thereset --hard
one, and this isn't exactly either of them.)git help branch
says " -f, --force Reset <branchname> to <startpoint> if <branchname> exists already. Without -f git branch refuses to change an existing branch."git branch -f master <hash>
and it's telling mefatal: Cannot force update the current branch.
Ummmm I have to do what now, check out some other random branch before I am allowed to use this command?HEAD
points to it).