Getting geeky with Git #5. Improving merge workflow with rebase

栏目: IT技术 · 发布时间: 4年前

内容简介:Merging is not the only utility that can integrate changes from one branch onto another. In this article, we look intoIn theRebase aims to rewrite git history so that it is simple and straightforward. To visualize it, let’s start with a clean repository:

Merging is not the only utility that can integrate changes from one branch onto another. In this article, we look into rebasing and learn how we can use it as an alternative to merging.

The basics of rebasing

In the previous part of this series , we’ve learned that merging can result in an additional  merge commit . This might not be the desired outcome if we aim for the readability of our git logs.

Rebase aims to rewrite git history so that it is simple and straightforward. To visualize it, let’s start with a clean repository:

echo "# rebase-repo" >> README.md
git init
git add README.md
git commit -m "Initial commit"
git remote add origin git@github.com:mwanago/rebase-repo.git
git push -u origin master

If you want to know the importance of the - u flag, check out the first part of this series .

Below, we simulate a very common situation. Imagine creating a new branch from master and starting to work on it. Before you finish up and want to merge it back to master, it contains some new changes.

git branch feature-two
echo "console.log('Feature one')" > feature-one.js
git add ./feature-one.js
git commit -m "Added the first feature"
git push origin master

Above, we create the feature - two branch and add some changes to the master. Now, our  feature - two is 1 commit behind the master branch. Let’s continue by adding some stuff to the feature - two .

git checkout feature-two
echo "console.log('Feature two')" >> feature-two.js
git add ./feature-two.js
git commit -m "Added the second feature"
git push origin feature-two

Now, both the master and the feature - two contain some new code. Let’s check the current state of the  feature - two with  git log :

commit 536676c27b51922b6e65568cebc1b7a9932704e0 (HEAD -> feature-two, origin/feature-two)  Author: Marcin Wanago <wanago.marcin@gmail.com>  Date: Sun Jul 26 18:35:46 2020 +0200
Added the second feature
commit b828ed40f9edd2aa56d99d4d351c624d7c6fbcef  Author: Marcin Wanago <wanago.marcin@gmail.com>  Date: Sun Jul 26 18:22:35 2020 +0200
Initial commit

Performing a rebase

To integrate those two, we could merge the feature - two into master, but that would create a merge commit. Instead, let’s use  rebase .

git rebase master
First, rewinding head to replay your work on top of it…  Applying: Added the second feature

Now, let’s see the git log again:

commit 6c943d260b6aa0fabfe77899babb8bb67ebb1e95 (HEAD -> feature-two)  Author: Marcin Wanago <wanago.marcin@gmail.com>  Date: Sun Jul 26 18:35:46 2020 +0200
Added the second feature
commit 318ff57e470d10dfe5924da38455b85dac667898 (origin/master, master)  Author: Marcin Wanago <wanago.marcin@gmail.com>  Date: Sun Jul 26 18:35:30 2020 +0200
Added the first feature
commit b828ed40f9edd2aa56d99d4d351c624d7c6fbcef  Author: Marcin Wanago <wanago.marcin@gmail.com>  Date: Sun Jul 26 18:22:35 2020 +0200
Initial commit

With rebasing, we re-wrote the history of the feature - two branch. When doing that, we moved all of the changes from master to the  feature - two branch and applied our changes on top of it.

The important thing is that when we rebased, Git created brand new commits when applying our changes on top of the commits from the master branch. To see it better, take a closer look at the above logs. We can see that the hash of our new commit changed.

commit 536676c27b51922b6e65568cebc1b7a9932704e0  Added the second feature
commit 6c943d260b6aa0fabfe77899babb8bb67ebb1e95  Added the second feature

Even though the above commits bring the same set of changes, they are different from the Git point of view.

Pushing our rebased changes

There is one important thing to cover here. If we would like to push the rebased version of our feature - two branch to our remote repository, we might encounter some issues. Let’s try to do so:

git push origin feature-two
To github.com:mwanago/rebase-repo.git  ! [rejected] feature-two -> feature-two (non-fast-forward)  error: failed to push some refs to ‘git@github.com:mwanago/rebase-repo.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.

The reason for the above is because we rewrote the history of our local feature - two branch and it no longer matches its remote counterpart. The most straightforward way to deal with it is to  force push it.

git push --force origin feature-two

Using the -- force option allows us to overwrite the remote branch even if our local version of it does not strictly match it.

This is not safe, though. Imagine someone else building up on top of your branch while you are rebasing. Using the -- force flag would cause all of that work to be erased. Instead, we can use the  -- force - with - lease flag.

git push --force-with-lease origin feature-two

The above flag is a safer option that refuses to update the branch if somebody updated the remote branch. Aside from that, you should use this option with some caution and perform it only on branches that you don’t expect anybody else to push to.

If you want to read more about -- fore - with - lease , check out this article on the Atlassian Developer blog.

Advantages of rebasing

In the previous part of this series , we’ve learned about the  fast forward merge . It can occur if there is a linear path between the source branch and the target branch.

We’ve committed to master after creating the feature - two branch. Even though that’s the case, we rewrote the history in a way that our  feature - two contains all the commits from the master branch.

Now, we can switch to the master branch and merge our changes.

git checkout master
git merge feature-two
Updating 318ff57..6c943d2  Fast-forward  feature-two.js | 1 +  1 file changed, 1 insertion(+)  create mode 100644 feature-two.js

The crucial thing above is the fact that we’ve performed a fast-forward merge . Let’s look into the  git log now:

commit 6c943d260b6aa0fabfe77899babb8bb67ebb1e95 (HEAD -> master, origin/feature-two, feature-two)  Author: Marcin Wanago <wanago.marcin@gmail.com>  Date: Sun Jul 26 18:35:46 2020 +0200
Added the second feature
commit 318ff57e470d10dfe5924da38455b85dac667898 (origin/master)  Author: Marcin Wanago <wanago.marcin@gmail.com>  Date: Sun Jul 26 18:35:30 2020 +0200
Added the first feature
commit b828ed40f9edd2aa56d99d4d351c624d7c6fbcef  Author: Marcin Wanago <wanago.marcin@gmail.com>  Date: Sun Jul 26 18:22:35 2020 +0200
Initial commit

As you can see, there is no merge commit whatsoever. By sticking to rebasing, we end up with a linear project history that we can easily follow from the tip down to the bottom.

When not to rebase

The most important thing about rebasing is not to do it on public branches. Above, we rebased master into our feature - two branch. Then, we’ve merged the  feature - two branch back to master using a  fast forward merge . While this is fine, doing it the other way would cause trouble.

Rebasing overwrites history, and we need to acknowledge that everybody on our team uses the master branch. Therefore, if we would rewrite the history in remote master, it would cause all of its local copies not to match. Since rebasing results in creating new commits under the hood, Git will think that the history of the remote master diverged from the local copies that our teammates maintain. Avoiding that is sometimes referred to as the golden rule of rebasing .

Summary

In this article, we’ve learned what rebase is and how to perform it. It certainly does have advantages and can simplify our Git history. On the other hand, before rebasing, we need to think if anyone else might use the branch that we are working on. When considering if we should rebase, we should take it into account. The goal should be improving our Git flow and not the other way around.

Rebasing has more functionalities that we can describe as interactive rebasing . It is a cool topic, and you can expect it in this series.


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

常用算法程序集

常用算法程序集

徐士良 编 / 清华大学 / 2004-1 / 48.00元

本书针对工程中常用的行之有效的算法而编写,其主要内容包括多项式的计算、复数运算、随机数的产生 、矩阵特征值与特征向量的计算、线性代数方程组的求解、非线性方程与方程组的求解、插值与逼近、数值积分、常微分方程组的求解、数学变换与滤波、特殊函数的计算、排序和查找。 书中所有的算法均用C语言描述,并存放在一张光盘上。 本书可供广大科研人员、工程技术人员以及管理工作者阅读使用,也......一起来看看 《常用算法程序集》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具