How to rebase your git branch
You worked on a branch and are ready to merge it into main. But main has changed since you started working on your branch. You need to rebase your branch on top of main.
You created a branch named b1
from main
and made 3 commits.
Your Git history looks like this:
alina
alina git:( b1 ) git log --graph --oneline --all
* 022a4c4 (HEAD -> b1, origin/b1) add B3.txt
* eeb98bb add B2.txt
* f9bcc02 add B1.txt
* 8dcf726 (origin/main, origin/HEAD, main) add A2.txt
* 22bdc8d add A1.txt
* 950c5f3 Initial commit
alina git:( b1 ) █
and corresponds to this graph:
Let’s imagine that you switch back to your main
branch and make a commit there.
alina
alina git:( b1 ) git switch main
Switched to branch 'main'
Your branch is up to date with 'origin/main'.
alina git:( main ) █
Instead of making a random commit, let’s assume you want to cherry-pick a commit from b1
into main
. You select the commit f9bcc02
and apply it on top of main
.
This commit added a file called B2.txt
:
alina
alina git:( main ) git cherry-pick eeb98bb
[main cd008e5] add B2.txt
Date: Fri Jul 7 08:04:20 2023 -0700
1 file changed, 1 insertion(+)
create mode 100644 B2.txt
alina git:( main ) ls
A1.txt A2.txt B2.txt README.md
alina git:( main ) git log --graph --oneline --all
* cd008e5 (HEAD -> main) add B2.txt
| * 022a4c4 (origin/b1, b1) add B3.txt
| * eeb98bb add B2.txt
| * f9bcc02 add B1.txt
|/
* 8dcf726 (origin/main, origin/HEAD) add A2.txt
* 22bdc8d add A1.txt
* 950c5f3 Initial commit
(END)
:11
(END)
alina git:( main ) █
Now, let’s return to your b1
branch. You want to rebase it on top of main
.
alina
alina git:( main ) git switch b1
Switched to branch 'b1'
Your branch is up to date with 'origin/b1'.
alina git:( b1 ) █
Your commit graph now looks like this:
The situation is as follows:
- The
main
branch has a commitcd008e5
that you don’t have onb1
, but it is a cherry-pick ofeeb98bb
, which you have onb1
. - The
b1
branch has 2 extra commits022a4c4
andf9bcc02
that you don’t have onmain
.
The git rebase
command will take the commits that are on b1
but not on main
, and apply them on top of main
by re-applying the changes they introduce on top of the commits on main
.
alina
alina git:( b1 ) git rebase main
warning: skipped previously applied commit eeb98bb
hint: use --reapply-cherry-picks to include skipped commits
hint: Disable this message with "git config advice.skippedCherryPicks false"
Rebasing (1/2)
Rebasing (2/2)
Successfully rebased and updated refs/heads/b1.
alina git:( b1 ) █
The git rebase
command is smart enough to realize that the commit eeb98bb
wouldn’t change anything on main
(because that commit was cherry-picked), so it skips it.
The commit graph is then as follows:
As usual, when in this state, a git push
will be rejected because the remote branch b1
is behind the local branch b1
.
alina
alina git:( b1 ) git push
To ssh://remote.mygit.com/gitpowerup/arenas.git
! [rejected] b1 -> b1 (non-fast-forward)
error: failed to push some refs to 'ssh://remote.mygit.com/gitpowerup/arenas.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
alina git:( b1 ) █
To push the changes, a git push --force-with-lease
is required. It is always risky to use the --force
option when pushing, so the --force-with-lease
option provides a safer alternative. It will fail if someone else has already pushed commits on b1
in the meantime.
alina
alina git:( b1 ) git push --force-with-lease
Enumerating objects: 10, done.
Counting objects: 100% (10/10), done.
Delta compression using up to 8 threads
Compressing objects: 100% (6/6), done.
Writing objects: 100% (9/9), 738 bytes | 738.00 KiB/s, done.
Total 9 (delta 2), reused 0 (delta 0), pack-reused 0
remote:
remote: Create a new pull request for 'b1':
remote: http://localhost:3030/gitpowerup/arenas/compare/main...b1
remote:
remote: . Processing 1 references
remote: Processed 1 references in total
To ssh://remote.mygit.com/gitpowerup/arenas.git
+ 022a4c4...c2b644e b1 -> b1 (forced update)
alina git:( b1 ) █
And your commit graph becomes:
On the server side, the commit graph is now in sync with your local repository.
There are a few dangling commits that will be cleaned up later by Git.