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: ** will
dev
Two additional commits on the branch are migrated tomaster
Branches; - ** Step 2: ** delete
dev
Two 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, through
git add
To include modification information in the staging area:
- Finally, through
git commit
Submit 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:
- in
A
Execute on branchgit merge B
, means willB
branchIncorporated into theA
Branches; - And in the
A
Execute on branchgit rebase B
Is displayed, indicating thatA
Branch by rebasingIncorporated into theB
Branches;
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 example
master
, the reference point is the latest commit node of the branch, i.eC
;- If it’s a
commit_id
, the reference point iscommit_id
Corresponding submission node;
1. Reference points are branches
Follow the above model:
- First of all,
dev
In addition to the reference point on the branchA
A copy of all nodes outside, i.eD'
andE'
, as a patch standby, and will branchdev
Point to a new reference pointC
:
- And then, the original
dev
The node order ofD->E
) apply the patch (Patch Applying
) to the new baselineC
And change the branch at the same timedev
To:
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 and
test
Branch pointing is changed to nodesB
And willtest
Commit nodes after the datum on the branch as patches:
- Then, patch them in order
C
andD
Apply to the new reference pointB
The back:
- In the end,
test
The 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 setrebase
Operation. Call after the patch is modifiedgit rebase --continue
To continuerebase
. A new commit is created;squash
: merge all commit nodes after the new base point, i.eC
andD
The 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:
- in
rebase
The default parameters are used in the processpick
New commits are not created as they would be if the new datum is a branch; - Once other parameters are used (e.g
reword
) 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 merge
andgit rebase
The significant difference is that the former will not be modifiedgit
The 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…