Mastering git, Part 12, git rebase

Combining Git commits with squash

Imagine you have done lots of commits, i.e. several commits for fixing a bug, but you don’t need all of them, and somehow you want to meld them and squash them into a single commit. You can use rebase. Git always squashes a newer commit into an older commit or “upward”. Let’s create some files:

Your tree would be something like this:

But now you would like to squash b-1, b2 and b-3 into one commit. So copy the hash ID of b-3 and execute rebase:

This will open your editor and the first few lines are:

Git will melt new commits into older ones, and we want to squash b-3 and b-2 into b-1 so change it into:

Close all instances of your editor and save them. This will open another editor to write a new commit message.

Write your new commit message and save it. Your new tree should look like this:

Squashing commits in git after push

Squash the commits locally (for the last N commits) :

force push them with + :

Refs: 1

Difference between --force and +:

Note that --force applies to all the refs that are pushed, hence using it with push.default set to matching or with multiple push destinations configured with remote.*.push may overwrite refs other than the current branch (including local refs that are strictly behind their remote counterparts). To force a push to only one branch, use a + in front of the refspec to push (e.g git push origin +master to force a push to the master branch).

Refs: 1

Rebasing branches onto the base

When you create a feature branch and start working on that, your master might grow and also your branch. Let’s create a repository and add “a” and b:

Then let’s create a feature branch for “c”

Now let’s get back to master and “d” and “e”:

 

At a certain point, you will decide to merge with the master branch, and your tree looks like this:

By doing this you will the following tree, which in a big project might become very complicated and difficult to track.

As you can see, the branch feature-c is 2 commits behind of the master branch.  You can rebase your feature branch onto the master branch, so you can make it as your feature branch has just branched from your master.

By doing so, you finally end up with a “linear history”. You can also give tags to your commits so you make your tree more readable:

If you want git to do a rebase instead of a merge when pulling:

or you can set it as the default action in your gitconfig file:

Rebase with a merge conflict

Let’s create a repository:

And create a feature branch and modify some files and add some files:

Now let’s switch back to master and update some files that have been updated in the feature branch:

Now let’s switch back to the feature branch and rebase it on master:

Now except for the first one, choose edit or reword for the rest, keep another terminal open terminal, and run

gitk --all

and save and close

 

Now

 

again:

Here we can merge conflict, so run:

Now in the above, since we are applying commits from the feature branch on master, B the local is master and C is the feature branch that we are applying changes from

 

 

 

 

 

 

undo a completed  rebase

If you’ve successfully completed a rebase and later decide you want to undo it, there are a few strategies you can use to reset or revert your branch to its state before the rebase. The method you choose depends on whether you’ve pushed the rebased commits to a remote repository and how you’ve managed your commits.

1. Using git reflog (Local Repository)

If you haven’t pushed your changes to a remote repository, you can use the git reflog command to find the commit your branch was at before the rebase and reset to it:

– Use git reflog to list the recent changes to your repository’s HEAD and branches, look for “rebase (start)” and choose the HEAD before that one

– Once you’ve identified the right entry, note the commit hash or the HEAD@{n} reference that points to your branch’s state before the rebase.
– Reset your branch to that state using:

 

2. Resetting After Pushing (Remote Repository)

If you know the exact commit your branch was at before the rebase, you can force reset your branch to that commit and force push it:

<commit-hash> is the commit ID of the branch before you started the rebase.

Reverting Using a New Commit:

If force pushing is not an option (e.g., due to team policies), you can revert the changes introduced by the rebase using git revert in a way that creates a new commit that undoes the changes:

This method creates a new commit on top of the current branch that undoes the changes brought by the rebase, without rewriting the branch’s history.

At any time, you abort and clean up the workspace operations by:

 

Rebase remote branch onto master

What if we have had pushed our changes into remote? On that occasion, you should “Rebase remote branch onto master”

This will remove your local feature-c repository, update references, and change to feature-c branch, but because you deleted it, this command will also download the origin/feature-c

Refs: [1]

How to determine if and when a branch has been rebased on the main

 

 

Rebase: rewriting Git history reword, delete, reorder  and Split

Refs 1,2, 3, 4

0 0 votes
Article Rating
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x