“This is the 13th day of my participation in the First Challenge 2022. For details: First Challenge 2022”
preface
An important reason for us to choose Git is its fast and convenient branch creation and switching. Based on the previous principle of Git, we will learn the related principle of Git branch today.
HEAD
HEAD is essentially a pointer to the current branch
ref: refs/heads/master
Copy the code
branch
We can actually think of a branch as a pointer to a COMMIT
The master branch is created by default during initialization, and the master does not point to any COMMIT
Branch creation
Creating a branch is essentially creating a pointer to a COMMIT (usually the current branch)
git branch dev
Copy the code
Branch switching
Switching branches actually points HEAD to a new branch
git checkout dev
Copy the code
Commit in the current branch
Commit results in a new COMMIT and moves the branch pointed to by the current HEAD to the front end
git add .
git commit -m dev
Copy the code
Branch merge
The merging of branches is what we usually call it
git merge barnch_name
Copy the code
Merging branches actually involves a number of different strategies, some of which are common
Fast-foward
If the branch to be merged is on the same commit chain as the current branch, Git will select fast-foward for us and simply move and update the current branch pointer
git merge dev
Copy the code
We can add parameters to produce a new COMMIT
git merge --no-ff
Copy the code
Recursive
The most common Merge strategy in Git merges is called tree-way Merge. The Recursive strategy is used when both the merging branch and the current branch have a commit that is different from each other.
-
Find the nearest common ancestor node
-
Generate merge commit based on Diff differences (common merge commit)
-
To deal with conflict
If there are no conflicts, Git automatically completes the merge and generates a new merge COMMIT to end the merge. However, if a conflict is encountered, we need to resolve the conflict and manually add the conflict file and execute continue.
git add .
git merge --continue
Copy the code
For conflicting files, we can also add parameters to automatically resolve highlighting. But we don’t actually advocate that.
git merge -Xours dev The conflict part is based on the current branch
git merge -Xtheirs dev The conflict part is subject to merge branch
Copy the code
How do I find the most recent common ancestor COMMIT
We can find the nearest common ancestor node by command
git merge-base --all branch_1 branch_2
Copy the code
In real development, it is possible to have more than one recent ancestor commit due to the merging of branches.
In this case, the two commit’s are actually merged into one virtual commit as our merged base
Ours
The Ours policy is very similar to the -xours argument mentioned above, but here Ours applies to all files and takes the current branch regardless of whether it is highlighted, in effect discarding all the contents of the branch to be merged. This is typically used when a feature is developed in two ways, with one remaining, but you can merge the commit from the other solution for later review.
thinking
- Why are Git branches created and switched so quickly?
Because the branch creation and switch are actually the creation and movement of Pointers to the corresponding commit, and because Git’s commit stores the full amount of data, it is also very fast to apply a commit file to the current workspace without the need for diff updates.
- Why does a Merge need a tree-way Merge?
The purpose of merging is to apply the changes of branch B to branch A, so we need A base node to compare branch B to get the actual changes of branch B, and of course, to get the changes of branch A by comparing branch A with base node. If both branches have made changes to a file, a conflict warning should be given, otherwise the latest changes from both branches should be applied.
- Merge the merge file into A branch. Merge the merge file into A branch. Merge the merge file into A branch.
This is usually the result of a merge conflict resolved last time. Let’s do this by example
We start with two branches A and B
We merged B into A1 to generate A2. At this time, A1 and B are in conflict. We retained the modification of A1 and abandoned the modification of B
We make a new commit to B to generate B1, at which point we merge B1 to A2
According to our previous analysis, the nearest common ancestor node, namely node B, will be found as the BASE at this time, and B, B1 and A2 will be combined in three ways.
The modification of B1 relative to B does not include the part we just conflicted, and the modification of A2 relative to B includes the part we just conflicted, so A2 will be considered as the latest commit and automatically merged.
So the part that was in conflict was neither regenerated nor prompted, and A2 code was applied directly.
conclusion
This article examines the nature of branching in Git and some common merge strategies to deepen our understanding of Git.
reference
- Git Merge Principle