1. The rebase principle

Summary of a.

  1. Rebase consolidates commit history and purifies commit history. It can also migrate branches, moving some branch commits to another branch
  2. Key strengths: Clean commits history, linear commits in git graph, reduced crosswalks, and easy code maintenance and management

Uhp explained that rebase activity can effectively clear commits history — which is widely used in commits to open source projects — and streamline Git workflows

B. Rebase and merge

The rebase function is to change the “base point” (parent commit) of a bunch of commits in a branch. This may not be easy to understand, so we can compare it to the common development operation merge — the purpose of this operation is similar: to merge changes to code from one branch to another

Git rebase = git merge git rebase = git mergeA simple version of the daily development environment composed of the Master branch and the Feature development branch. In the example, the same workflow is implemented with two commands to compare their similarities and differences and understand how Rebase works. As shown in the figure above, consider a simple daily working environment: when you are working on a new Feature branch based on Commit 2, there are some new commits in the Master branch, and you need to synchronize the Master update on your branch.

1. Use merge

Git pull = git fetch + git merge In general, we use the following command:

Git checkout feature // Switch active branch to feature (featureCopy the code

This creates a new “Merge Commit” in the feature branch (Commit 8 in the figure below), linking the histories of the two branches, resulting in the branch structure shown below:Merge is a common operation that merges code changes on two branches, leaving the branch structure intact and using a new COMMIT. Using merge, you can avoid all possible problems with rebase.

On the other hand, this means that every time we synchronize code from the Master branch in the Feature branch, we get a virtually meaningless MERGE COMMIT node (Commit 8 in the figure). This creates two problems:

  1. If we need to pull the latest code from the Master branch multiple times, multiple merges will pollute our commit records, making them jumbled, less readable, and less maintainable.
  2. Merge causes two branches to intersect, forming a “diamond chain”. This makes our Git Graph messy and difficult to manage and maintain.

2. Use rebase

In the same scenario, you can use the following command to rebase the feature branch to the master branch:

git checkout feature
git rebase master
Copy the code

Before rebase, the three commit(3, 4, 5) of the Feature branch were based on Commit 2. By executing git rebase, the base point of the Feature branch becomes commit 7.

In effect, what rebase does is create a copy of the three commits on the Feature branch (commit 3,4,5) and move that copy to the top of the master branch, effectively integrating all new commits from the Master branch. To be specific: Git will make the commit sequence we want to move (commit 3, 4, 5) reappear on the Master branch in the same order as a copy — 3′, 4′, 5′, with the same modifications, author, date, and comment information as 3, 4, 5. The difference is that rebase these copies have a new COMMIT ID that is different from the original commit.

As with the merge operation, after the rebase operation, the Feature branch successfully integrates all updates from the Master branch.

C. Summary of advantages and disadvantages:

Git Git Git Git Git Git Git Git Git Git Git Git Git

There is no difference in the end result between the two consolidation methods, but the rebasing makes the commit history cleaner. When you look at the history of a rebase branch, you see that although the actual development work is in parallel, it appears to be serial, and the commit history is a straight line with no forks.

In plain English, the main benefit of using Rebase is a clearer commit history. It eliminates unnecessary Git merge merge results in merge commit; At the same time, as shown above, the rebase operation produces a linear Git Graph structure. We can trace from the top of the feature branch all the way back to the beginning of the project without any forks — this gives us a better understanding of the change history of the project.

However, rebase operations are more complex and dangerous than merge operations. It rewrites the history of a project, which can have a huge impact on the work of others. Also, the merge commit attached to the merge operation can indicate when changes upstream (the Master branch) have been merged. With the rebase operation, we can’t get such a hint.

2. Examples in workflow

Before we get into the commits section, we need to emphasize that all rebase actions cause changes to the history of commits, so when we want to push a rebase change to a remote repository, Git considers the activity to be a “dangerous activity” and needs to be usedgit push --forceTo force a push. This requires a clear understanding of what we’re doing, and that’s what this article is all about: getting people to stop being afraid of Rebase and use it where it suits them and optimize their Git flow.

A. Merge multiple commits from different branches: avoid redundant merge commits

In a working environment similar to the above (after local development, synchronize the latest code from the master online, and then merge it with the Master), do the following separately, and observe the commit history log online

//# (feature)git pull origin master git checkout master (master)git merge feature (feature)git rebase master git checkout master (master)git merge featureCopy the code

As you can see, with the Rebase operation, we have streamlined the commit history. Git Graph also ensures an intuitive linear structure (see below)

B. Merge multiple commits of the same branch: rebase -i operation

In our daily work, when we are working on a feature under the same development branch, we will constantly modify and fine-tune the code as requirements are changed, testing is advanced, and then commit and push it online. Multiple commits don’t make sense. We can rewrite multiple commits in the same branch using rebase –interactive to merge multiple commits into one.

Suppose we commit three times on branch feature-d, as shown in the figure below:Git rebase -i HEAD~num: git rebase -i HEAD~num

Git rebase -i HEAD~3Copy the code

Git generates the following text on the terminal (command line). Enter vi to enter the editing modeTwo things to watch out for in this list:

  • The oldest submission in the list is at the top, and the most recent is at the bottom, with usegit logThe view order is reversed, the order isInteractive rebaseThe operation sequence of.
  • The words before hash indicate the operations for the submission, which can be:
# Commands: # r, reword = use commit, but edit the commit message # p, pick = use commit Next comes a page that lets us write a new submission. # e, edit = use commit, but stop for amending Git add. => git commit --amend After committing, use git rebase --continue to rebase. If you want to modify a commit, you can use this method # s, squash = use commit, but meld into previous commit to merge the commit. This will merge the commit into the previous commit and allow us to reedit the commit information, which is what we're going to do. # f, fixup = like "squash", but discard this commit's log message Exec = run command (the rest of the line) using shell discards the commit, i.e. the commit will not be copied over. # d, drop = remove commitCopy the code

If you want to merge all three commits onto the oldest commit, you need to change the actions for the last two commits tosquashThat is as follows:After the above changes are complete, a new text editing page is displayed, allowing us to write new comments for the new commit after merging, as shown belowGit push –force is required because we have done a local “three-in-one” operation that encapsulates and overwrites the three original commits with a new commit, which involves changing the commit history. After completion, the picture is as follows:Click on the 9f830b9 commit, as shown in the figure below. The details of the three initial commits before the rebase-i operation are reserved for comments.To summarize, we overwrite the three original commits with a new commit through rebase-i, editing the new overview comments while preserving the three original commit comments.

At this point, suppose we want to synchronize the code from the online branch and merge it into the master branch, do the following:

(feature-D)git rebase master
git checkout master
(master)git merge feature-D
Copy the code

In the same workflow, the commit history is much simpler with the Rebase series of operations.

C. Simplify git Graph effects under complex projects

Imagine a Git structure like the following: new functionality development based on online branch (master); Once development is complete, we need to synchronize the latest code from the master online branch, and then synchronize the development branch content to the test branch.Do not use/rebase respectively, the operation code, the effect is as follows:

// left (dev -b) git pull origin master git checkout st (st) git rebase master git checkout st (st) git merge dev-BCopy the code

Merge Commit information can be completely avoided if the rebase command is used more fully in the same workflow, such as before merging to the ST branch and then merging to the ST branch. For example, if you use rebase-i before committing, you can summarize and reduce multiple COMMIT commits.

3. Frequently Asked Questions and solutions

A. Rebase eliminates submission history and even affects others — the golden rule

Follow the golden rule stated and emphasized in the Git documentation: Never rebase a common branch on another branch. Here’s a bad example: The following is wrong

Git rebase feature-xx git rebase feature-xxCopy the code

So what should we do? Git Git:

If commits exist outside of your repository and someone else may be developing on them, don’t base them

If you follow this golden rule, nothing will go wrong. Otherwise, the people will hate you, and your friends and family will laugh at you and spit on you. As a general rule, only base cleanup history on local changes that haven’t been pushed or shared with others, and never base commits that have been pushed elsewhere, so you can get the benefit of both approaches.

To put it more bluntly, as long as you limit rebase to your own branch of development, it won’t affect anyone else; Rebase is a great tool to optimize your commit history and streamline your commit if you follow the golden rule.

B. Rebase will cause more conflicts. How can it be avoided?

  1. Overview of the problem: In addition to the possibility of overwriting commit history and requiring push –force overwriting, rebase operations have a common complaint that they encounter more conflicts than normal operations.
  2. Formation reason: Multiple commits have been made in [local development branch feature]. When rebase to [branch master to be merged], if there is a conflict between the feature branch and the master branch during development, each commit of the feature needs to manually resolve a conflict.
  3. Graphic examples of problems, solutions: blog.csdn.net/weixin_4405… The -i operation can effectively solve this problem. For details, see the link

4. Use Rebase in real work

When I am writing this article, I have just completed the research and document output of Rebase operation under the guidance of the team leader, and I am pushing forward its application in the team. The following three points are the scenarios that I think can better use the advantages of Rebase operation. In my scenario, if rebase is well understood, they will be able to plug into existing workflows relatively quickly. Predictably, of course, the actual working process, there are more complicated than imagined, are warehouses and branch of collaborative development, therefore in the process of advancing the rebase operation is bound to encounter many problems, I want to be able to output through this article to record my some preliminary superficial idea at the moment, have the effect of a little point topic, I would love to see them correct my mistakes and give some examples that are really easy to apply.

A. During development: Reduce merge commit with rebase

The local development branch usually pulls remote code before starting a new day of development, which can be done using rebase(or pull –rebase). The benefit of doing this is to make git Graph clearer and reduce redundant Merge commit records

B. Before entering the code

First, rebase the local development branch (such as feature) to the branch to merge (such as master). After this rebase operation, switch to the master branch to merge feature. The examples in the Official Git documentation express this idea, and the benefits of doing so are concise commits and Git graphs.

C. In the case of continuous modification

Rebase-i can be used in the local development branch to reduce the commit record and avoid the occurrence of too redundant history before the local development branch fixes some small bugs repeatedly and commits to the remote repository:

Commit 1: complete the 'XXX' function; Commit 2: fix bug1 in 'XXX' function; 3. Commit 3: fix bug2 with 'XXX' function; 4. Commit 4: add 'YYy' functionality missing from 'XXX' functionality;Copy the code

This whole string of commits can be combined into one total commit: complete the development of ‘XXX’ functionality and bug fixes, and then merge into a remote online branch to avoid multiple unnecessary commit records.

Reference 5.

  1. Introduction to some basic operations and teamwork juejin.cn/post/684490…
  2. Git -rebase git-scm.com/book/zh/v2/…
  3. Yrq110. me/post/tool/g…
  4. Nuggets on the actual operation speak a better article juejin.cn/post/684490…