Git - Pull, Merge and Rebase
Git Pull
git pull
is an alias for git fetch && git merge
What if you want to use rebase
instead of merge
with git pull
? git pull --rebase
How to pull the latest changes into your branch without creating an extra merge commit? Run this command multiple times a day when working to avoid merge conficts.
If there is a merge conflict when you run this, drop the --ff-only
flag to deal with the conflict asap. This avoids merge conflicts later.
To pull from main
git pull origin main --ff-only
To pull from develop
git pull origin develop --ff-only
You can also configure git to only allow fast forwards on pulls without having to set it everytime:
git config --global pull.rebase true
https://spin.atomicobject.com/2020/05/05/git-configurations-default/
Unrelated histories
The refusing to merge unrelated histories
error happens when you attempt to merge branches or repositories that Git perceives as having no common commit history.
To resolve the refusing to merge unrelated histories
error, you need to instruct Git to allow merging of unrelated histories. This can be done using the --allow-unrelated-histories
flag.
git pull origin main --allow-unrelated-histories
git merge origin/main --allow-unrelated-histories
Merging
Merge from a remote branch into a current branch

Checkout a different branch and Merge from another remote branch into that branch

Allows developers to merge Git branches while the logs of commits on branches remain intact.
Rebasing
Move work from the feature branch onto the main branch

It will result in this:

Lets users integrate changes from one branch to another. Once the action is complete, the logs are modified. Git rebase was developed to overcome merging’s shortcomings, specifically regarding logs.
Git merge, on the other hand, only changes the target branch and creates a commit, preserving the history of the source branch.
When pulling changes, should I merge or should I rebase?
TLDR: You don’t need to preserve a linear commit history. That is not necessary. Other developers on the team will be pissed if their changes or the commit history about their changes is messed with. What is the point of maintaining a linear commit history? To me, that seems totally un-necessary. Just use merge
while pulling changes down until a more customized approach is necessary - especially when you have changes in local branch. If the local branch is clean, then there is no difference between merge and rebase when pulling changes down.
In most situations, you should rebase instead of merging down if you want a clean, linear commit history, especially when working on a feature branch that is not shared with other developers; however, if you need to preserve the exact chronological order of commits or are collaborating with others on a branch, then merging is the better choice as it avoids rewriting history.
Merge is best used when the target branch is supposed to be shared. Rebase is best used when the target branch is private. Merge preserves history. Rebase rewrites history.
Git rebase compresses all the changes into a single patch and integrates this new patch onto the target branch. Then, it moves the completed work from one branch to another, typically the master branch. In the process, rebase flattens the history, removing unwanted entries.
Resolving merge conflicts after a Git rebase
When you perform a git rebase
operation, you’re typically moving commits around. Because of this, you might get into a situation where a merge conflict is introduced. That means that two of your commits modified the same line in the same file, and Git doesn’t know which change to apply.
After you reorder and manipulate commits using git rebase
, should a merge conflict occur, Git will tell you so with the following message printed to the terminal:
error: could not apply fa39187... something to add to patch A
When you have resolved this problem, run git rebase --continue
If you prefer to skip this patch, run git rebase --skip
instead.
To check out the original branch and stop rebasing, run git rebase --abort
Could not apply fa39187f3c3dfd2ab5faa38ac01cf3de7ce2e841... Change fake file
Here, Git is telling you which commit is causing the conflict (fa39187). You’re given three choices:
- You can run
git rebase --abort
to completely undo the rebase. Git will return you to your branch’s state as it was before git rebase was called. - You can run
git rebase --skip
to completely skip the commit. That means that none of the changes introduced by the problematic commit will be included. It is very rare that you would choose this option. - You can fix the conflict.
To fix the conflict, you can follow the standard procedures for resolving merge conflicts from the command line. When you’re finished, you’ll need to call git rebase --continue
in order for Git to continue processing the rest of the rebase.
Git Interactive Rebase
Git cherry-pick is great when you know which commits you want (and you know their corresponding hashes) – it’s hard to beat the simplicity that cherry-pick provides.
But what about the situation where you don’t know what commits you want to pick? Thankfully, Git has you covered there as well! We can use interactive rebasing for this – it’s the best way to review a series of commits you’re about to rebase.
All interactive rebase means Git is using the rebase command with the -i option.
If you include this option, git will open up a UI to show you which commits are about to be copied below the target of the rebase. It also shows their commit hashes and messages, which is great for getting a bearing on what’s what.
When the interactive rebase dialog opens, you have the ability to do many things:
- You can reorder commits simply by changing their order
- You can choose to keep all commits or drop specific ones.
- squashing (combining) commits
- amending commit messages
- editing the commits themselves
Here’s a development situation that often happens: I’m trying to track down a bug but it is quite elusive. In order to aid in my detective work, I put in a few debug commands and a few print statements.
All of these debugging / print statements are in their own commits. Finally I track down the bug, fix it, and rejoice!
Only problem is that I now need to get my bugFix back into the main branch. If I simply fast-forwarded main, then main would get all my debug statements which is undesirable. There has to be another way…
We need to tell git to copy only one of the commits over. We can use the same commands:
git rebase -i
git cherry-pick