“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.

  1. Find the nearest common ancestor node

  2. Generate merge commit based on Diff differences (common merge commit)

  3. 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

  1. 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.

  1. 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.

  1. 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