Welcome to github.com/hsfxuebao/j… , hope to help you, if you feel ok, please click on the Star

preface

Git cherry-pick and Git rebase are introduced in this section.

A, Git cherry – pick

Git cherry-pick is used for porting commit. For example, the dev branch mistakenly commits 2nd and 3rd twice, if you want to port those two commits to the master branch. Using the delete and then add method would be tedious, but with cherry-pick you can easily achieve this requirement.

We first created two branches in the repository, master and dev, and simulated the above scenario:

As you can see, there are two commits on the dev branch and only one commit on the Master branch. Now you want to port these two commits to the Master branch. The whole is divided into two steps:

  • ** Step 1: ** willdevTwo additional commits on the branch are migrated tomasterBranches;
  • ** Step 2: ** deletedevTwo additional commits on the branch;

1. The first step

git cherry-pick commit_id

First switch to the master branch, and then migrate the two commits on the dev branch to the master branch using the following command:

3rd submit git cherry-pick aec8c copy codeCopy the code

009DD and aEC8C represent the SHA1 values for commit 2nd and 3rd to be migrated, respectively:

The migration process is as follows:

  • As shown in the figure above, the cherry-pick instruction is executed twice, creating two commit objects 50477 and F05A0 with the same content as 2nd and 3rd. Therefore, the essence of cherry-pick instruction migration submission is: copy the commit to be migrated first, and then splice it to the master branch.

  • Commit 2nd and commit 3rd in the same order.

  • If you migrate 3rd first, merge conflicts will occur and need to be resolved manually:

Run the vi test. TXT command to view the test. TXT file that contains a merge conflict.

The test.txt file in the initial commit on the master branch does not intuitively conflict with the test.txt file in the commit 3rd.

But why do merge conflicts occur? The reason is the three-way merger principle:

If you want to merge commit E in dev and commit B in master, you should first find the common parent node A of B and E, and then perform A three-way merge based on B and E.

Understanding the three-party merger principle can explain the causes of merger conflicts above:

  • Because commit 3rd is created based on commit 2nd, actions to files in 2RD are kept on 3rd.

  • If you concatenate 3rd directly after initial COMMIT, you lose commit 2nd.

  • If you submit 3rd, you can’t find the public commit node init by submitting 2nd, which will cause the merge to fail.

So, regardless of whether the contents conflict, the merge process will conflict:

** Solution: ** Manual merge three steps:

  • First, resolve the conflict by choosing what to keep:

  • And then, throughgit addTo include modification information in the staging area:

  • Finally, throughgit commitSubmit modification information:

Check the commit history of the master branch:

You can see that by resolving the conflict and manually merging, the entire cherry-pick process is successfully completed. The new commits are manual merge commits, not copied commits.

2. The second step

At this point, the states of the two branches are:

The next step is to remove the two incorrect commits 2nd and 3rd on the dev branch, which are equivalent to version rollback; There are three methods you can use: Revert, Reset, and checkout, both of which are demonstrated here.

Use the checkout

First switch to the dev branch and then switch to commit initial COMMIT with the following command:

Git checkout dd703 is the SHA1 value of the commit initial_commitCopy the code

At this point, the node is in a free state:

Then delete the dev branch:

Because the dev branch is not merged with the master, the -d parameter is used to forcibly delete the dev branch.

After deletion, the master branch and free commit are left. Set the free node to the dev branch with the following command:

Git checkout -b dev copies the codeCopy the code

Thus, the dev branch is returned to its pre-commit state by stealth;

Use the reset

Using checkout only moves the HEAD pointer, not the dev branch pointer, so there are floating commit nodes. Reset, which moves the HEAD and dev branch Pointers synchronously, does not cause this problem. So using reset for version rollback is much easier:

Git reset --hard dd703Copy the code

Git rebase

First of all, rebase has two meanings: change base and derivative, that is, the reference point of the transformation branch. By default, the first commit on the branch is used as the base point. The master branch uses commit 1st as the base point by default, as shown in the following figure:

If you commit 4th as the basis for the master branch, the master branch will become:

This process of changing base points is called rebase;

Rebase is very similar to Merge, but the way they work is significantly different. For example, merge branches A and B:

  • inAExecute on branchgit merge B, means willBbranchIncorporated into theABranches;
  • And in theAExecute on branchgit rebase BIs displayed, indicating thatABranch by rebasingIncorporated into theBBranches;

Merge and rebase

1. Merge branches

Now there are two branches origin and myWork, so if you want to merge the Origin branch into the MyWork branch. According to the three-way merge principle, we need to merge on the basis of C4, C6 and their common parent commit node C2:

The merge results in a new commit, C7, which has two parents, C4 and C6. If there are no conflicts, Git will automatically merge them in the fast-forward mode. If there are conflicts, git will resolve them and then merge them manually.

2. Merge branches using Rebase

Since it is the myWork branch that needs to merge to the Origin branch, we first switch to the MyWork branch (note that this is the opposite of the branch where the merge method was used) :

Git checkout mywork copies the codeCopy the code

Then merge:

Git rebase Origin copies the codeCopy the code

The combined results are as follows:

** Note: The merged origin branch remains fixed, whereas the merged myWork branch applies its submissions one by one as patches to the submissions that origin points to;

Git automatically creates c5′ and c6′ during this process. Git gc will collect c5 and C6 from git gc. The commit record of the merged branch myWork becomes a straight line:

That is, rebase applies the commit from mywork to Origin and modifies the commit record from mywork.

4. Rebase principle analysis

As shown in the figure, both the master and dev branches use commit node A as their reference point:

If the dev branch wants to transform the reference point A, then:

** Step 1: ** switch to the dev branch;

** Step 2: ** Run git rebase master.

The rebase parameter in the command above specifies the changed reference point:

  • If it is a branch, for examplemaster, the reference point is the latest commit node of the branch, i.eC;
  • If it’s acommit_id, the reference point iscommit_idCorresponding submission node;

1. Reference points are branches

Follow the above model:

  • First of all,devIn addition to the reference point on the branchAA copy of all nodes outside, i.eD'andE', as a patch standby, and will branchdevPoint to a new reference pointC:

  • And then, the originaldevThe node order ofD->E) apply the patch (Patch Applying) to the new baselineCAnd change the branch at the same timedevTo:

Additional patchD':

Each time a patch is applied to a new baseline, three options appear:

git rebase –continue

After resolving the merge conflict, continue to apply the remaining patch E’ :

git rebase –skip

Skip the current patch and proceed to the next patch:

If this option is executed until the patch on branch dev is applied, the states of both branches after rebase are as follows:

git rebase –abort

This option terminates the rebase operation and returns to the state before the rebase command was executed:

2. The reference point is submission

The process,

As shown in the figure, if submitting node B is used as a reference point, execute on the current test branch:

Git rebase 3ccc8 replicates the codeCopy the code

After the original nodes C and D are directly applied to the new reference point B, it is equivalent to that there is no change. The base-changing process is as follows:

  • First, base points andtestBranch pointing is changed to nodesBAnd willtestCommit nodes after the datum on the branch as patches:

  • Then, patch them in orderCandDApply to the new reference pointBThe back:

  • In the end,testThe state of the branch is:

Git rebase 678e0 doesn’t change anything:

However, we can enter reBase interaction mode by adding the -i parameter to rebase, which allows a series of operations to be performed on a particular patch during the Rebase operation;

Practical demonstration

First four commits are made on the test branch:

Execute the following command to change the reference point of the test branch to commit node B (678E0) and base it:

Git rebase -i 678e0Copy the code

After executing this command, the vim editor will enter:

You can change the pick parameter as needed to the following parameters that represent different functions; This allows different operations to be performed on nodes C and D. Such as:

  • pick: Default parameter, indicating that no operation is performed on the submission node and the original submission node is directly applied. Do not create a new commit;
  • reword: Applies the copied original commit node, but you can edit the commit information for that node. With this parameter, you can modify the commit information for a particular commit. A new commit is created;
  • edit: The original commit node after application replication will stop on the patch with this parameter setrebaseOperation. Call after the patch is modifiedgit rebase --continueTo continuerebase. A new commit is created;
  • squash: merge all commit nodes after the new base point, i.eCandDThe two nodes are merged. A new commit is created;
  • There are other parameters that I won’t go through here.

This time use the default pick parameter, save and exit the vim editor through :wq to complete the rebase operation:

Before the rebase operation:

You can see that when the new datum is committed for a specific purpose:

  • inrebaseThe default parameters are used in the processpickNew commits are not created as they would be if the new datum is a branch;
  • Once other parameters are used (e.greword) a new commit is created when a patch is changed;

Five, rebase matters needing attention

  • Do not rebase on the master branch, otherwise it will cause a lot of problems (master must be a remote shared branch).

  • In general, branches that perform Rebase are their own local branches. Never use Rebase on remote branches that are shared with others.

    Understandably, code on a remote branch may have already been cloned locally by someone else, and if you change the commit history of the remote branch with Rebase, you’ll need to do a complex merge every time someone pulls code locally.

  • Therefore, git rebase is recommended for merging non-master branches locally, and git merge is recommended for merging other branches.

Note:git mergeandgit rebaseThe significant difference is that the former will not be modifiedgitThe submission record, while the latter will!

6. Rebase applications

1. Merge branches

Git merge uses the principle of three-way merge. Without a common commit node, git merge cannot be performed. You can use rebase to merge git. As shown below:

The local master branch and the remote master branch do not have a common commit node and cannot use Git merge. Rebase can be used for merging:

Git rebase origin/master copies the codeCopy the code

The status of the local master branch after the merge is:

2. Modify specific commits

The following situations are suitable for rebase when backing back and making changes:

For example, three commits were made on the master branch:

Go back to commit 2nd and modify the commit information:

When we go back to the 3rd submission, we find that the previous changes have not been saved:

You can use Rebase at this point, with commit 1st as the new commit node (as explained in point 4). First execute:

Git rebase -i 5ab3f Copies the codeCopy the code

Enter interactive mode by adding the -i parameter and change the default pick parameter of submit 2nd to the reword parameter:

After saving the Settings and exiting, the page for modifying the submission information is displayed:

Save and exit to complete the modification:

Rebase

To demonstrate, create two additional branches, dev and test, and commit twice on each branch:

They have a common parent commit node init, where the state of the local repository is as follows:

  • Because the test branch needs to be regrounded to merge into the dev branch, you need to switch to the test branch first, which is the opposite of the merge operation.

  • Then run the following command on the test branch to rebase the branch:

    Git rebase dev copies the code

I test branch, now I want to redefine my base point, using the commit to which the dev branch points as my new base point. The process is as follows:

  • First, the commit (patch) TES1 on the Test branch is applied to the tail of the new baseline dev2, and a merge conflict occurs:

    Dev2 commits 361be (dev); dev2 commits 361be (dev); dev2 commits 361be (dev); dev2 commits 361be (dev)

As shown, there are three options:

  • Git rebase — Abort: Abort the rebase operation.

  • Git rebase –skip: discard the patch of the current test branch. If this option is executed all the time, the status of the two branches is as follows:

    The test branch has the same file as the dev branch:

    And the commit record on the test branch is changed to the commit record on the dev branch:

    This is what happens if you keep running git rebase –skip and discard all test branch patches:

  • Git rebase –continue

    Add two commits dev3 and dev4 to dev branch:

    Switch back to the test branch and add tes3 and TES4 commits twice:

    At this point, the states of the two branches are:

    Git rebase dev on the test branch causes a collision with tes3, the first patch on the test branch:

    Open the test. TXT file and resolve the conflict manually:

    Delete lines 4, 7, 9:

    After the conflict is resolved, run git add to add the changes to the file ‘ ‘test.txt’ to the staging area to indicate that the conflict is resolved:

    ** Note: ** there is no need for a commit, just continue with the rebase operation;

    Git rebase –continue to work on the next patch of the test branch:

    After rebase completes, look at the commit record for the test branch:

    You can see that the commit history of the Test branch has been modified to achieve the desired merge effect.

    And, at this time the test on the branch with tes4 tes3 twice before commit SHA1 value and perform rebase both commit SHA1 value is not the same:

    This verifies that Git will automatically create commit nodes during the rebase process. The status of the dev and test branches is as follows:

    Git merge test if you run git merge test on the dev branch, you should use the fast-forward method:

    This state can be expressed more intuitively using gITk:

As you might have noticed, rebase is very similar to cherry-pick. Except that cherry-pick doesn’t modify the branch commit record, whereas Rebase does.

Merge and Rebase options

Follow Rebase’s golden rule when using it: Never use Rebase on a public branch. The common branch can be understood as the master branch. Because Rebase overwrites the branch commit record, it poses a risk to project backtracking. Here’s how it differs from merge:

  • Git merge is a merge operation. Git merge is a merge operation. However, it has the advantage that it does not modify any of the commits and saves all of them in their entirety, making it easy to trace back. And only branches with common commit nodes can be merged;

  • Rebase does not merge; it simply copies changes made by the current branch to the last commit of the target branch. Therefore, it can not be constrained by the three-party merge principle and merge branches without common commit nodes.

    Using Rebase modifies the commit history, resulting in a cleaner branch commit history. It’s like writing a book. You only publish the final version, not the previous draft. However, be careful not to use Rebase on shared branches.

Both are powerful branch consolidation commands, depending on the situation.

Rebase, reset, revert

The names of these three directives are similar and confusing. The following table compares their uses and differences:

Git best practices

Now you can fully understand the general steps of using Git to push files from a local repository to a remote repository:

  • ** Create a local repository:

    Git init copies the codeCopy the code
  • ** Add user information:

    Git config --global user.email '[email protected]Copy the code
  • ** Add remote storage address:

    Git remote add origin copy code at https://www.github.com/exampleCopy the code
  • ** Step 4: ** Modify the file;

  • ** Step 5: ** Place files in workspace into staging area:

    Git add. copy the codeCopy the code
  • ** Step 6: ** Commit files from staging area to version repository:

    Git commit -m 'comment' copy codeCopy the code
  • ** Step 7: ** Sync with remote repository:

    Git pull --rebase origin master copies codeCopy the code
  • ** Step 8: ** Establish the connection between the local branch and the remote branch, and push:

    Git push -u origin master copy codeCopy the code

After learning in this section, you will be familiar with the principles and usage of cherry-pick and Rebase. The next section will cover Git sublibraries: SubModule and Subtree. Looking forward to seeing you again!

Reference: juejin. Cn/post / 684490…