Skip to content

Rebase, Squash, Merge

Create an Issue, a Corresponding Pull Request and a Branch

Before you develop a feature or fix a bug, first open an issue in Github and describe the work you want to do.

Then, create a branch.

Push your codes to the branch. When the work is finished, create a pull request and assign it to someone to review.

If everything goes well, rebase and squash the commits and merge it into the main branch.

graph LR

issue(Open an Issue) --> branch(Branch) --> push(Push Codes)
push --> pr(Pull Request) --> review(Code Review) --> merge(Rebase, Squash and Merge)

Develop on Feature 2

Now let's explore the workflow from an example.

We are working on branch feature-2, and pushed two commits to the branch. Someone is working on branch feature-1.

%%{init :{"gitGraph": {"mainBranchName": "main"}}}%%
gitGraph
commit id: "m1"
commit id: "m2"
branch feature-1
commit id: "f1"
checkout main
branch feature-2
commit id: "f2-1"
commit id: "f2-2"
git checkout feature-2

git add file1.txt
git commit -m "f2-1"

git add file2.txt
git commit -m "f2-2"

git push origin feature-2

Feature 1 Branch Merged

Now branch feature-1 is merged into main.

%%{init :{"gitGraph": {"mainBranchName": "main"}}}%%
gitGraph
commit id: "m1"
commit id: "m2"
branch feature-2
commit id: "f2-1"
commit id: "f2-2"
checkout main
commit id: "f1"
git checkout main

git merge feature-1

Merge

Below is the current git graph, how can we merge branch feature-2?

%%{init :{"gitGraph": {"mainBranchName": "main"}}}%%
gitGraph
commit id: "m1"
commit id: "m2"
branch feature-2
commit id: "f2-1"
commit id: "f2-2"
checkout main
commit id: "f1"

Merge Commit

A merge can be done by creating a merge commit.

%%{init :{"gitGraph": {"mainBranchName": "main"}}}%%
gitGraph
commit id: "m1"
commit id: "m2"
branch feature-2
commit id: "f2-1"
commit id: "f2-2"
checkout main
commit id: "f1"
merge feature-2
git checkout main

git merge feature-2

Be careful if you want to use a merge commit.

Merge commit can mess up the git graph, especially when there are lots of merge commits and lots of conflicts in the graph.

When we need to debug, trace back or reset, it may create unnecessary inconvenience.

So, do this the right way. Otherwise, you'll most likely end up as below, or even worse.

%%{init :{"gitGraph": {"mainBranchName": "main"}}}%%
gitGraph
commit id: "m1"
commit id: "m2"
branch feature-1
commit id: "f1-1"
commit id: "f1-2"
checkout main
branch feature-2
commit id: "f2-1"
branch temp1
commit id: "tmp-1-1"
branch temp2
commit id: "tmp-2-1"
commit id: "tmp-2-2"
checkout temp1
commit id: "tmp-1-2"
checkout feature-2
merge temp1
commit id: "f2-2"
checkout main
merge temp2
merge feature-2
merge feature-1

Fast Forward Merge

Rebase

Before rebase:

%%{init :{"gitGraph": {"mainBranchName": "main"}}}%%
gitGraph
commit id: "m1"
commit id: "m2"
branch feature-2
commit id: "f2-1"
commit id: "f2-2"
checkout main
commit id: "f1"

Rebase Without Squash

%%{init :{"gitGraph": {"mainBranchName": "main"}}}%%
gitGraph
commit id: "m1"
commit id: "m2"
commit id: "f1"
branch feature-2
commit id: "f2-1"
commit id: "f2-2"
git checkout feature-2
git rebase -i main
# pick all the commits

Rebase With Squash

%%{init :{"gitGraph": {"mainBranchName": "main"}}}%%
gitGraph
commit id: "m1"
commit id: "m2"
commit id: "f1"
branch feature-2
commit id: "f2-1"
git checkout feature-2
git rebase -i main
# squash all the commits into one

Merge

%%{init :{"gitGraph": {"mainBranchName": "main"}}}%%
gitGraph
commit id: "m1"
commit id: "m2"
commit id: "f1"
commit id: "f2-1"
git checkout main

git merge feature-2

Is there another way?

Yes. You can explore more options from here: how-do-i-squash-my-last-n-commits-together

TLDR, git merge --squash or git reset --soft HEAD~3 && git commit.