Home>Article>Development Tools> Detailed analysis of git-merge (organized and shared)

Detailed analysis of git-merge (organized and shared)

WBOY
WBOY forward
2022-03-07 17:24:03 5413browse

This article brings you relevant knowledge aboutGit, which mainly introduces the related issues of git-merge. The git-merge command is used to merge from specified commit(s) to The operation of the current branch, I hope it will be helpful to everyone.

Detailed analysis of git-merge (organized and shared)

Recommended study: "Git Tutorial"

1.1 Summary

In the git-merge command , there are the following three parameters:

  • git merge [-n] [--stat] [--no-commit] [--squash] [--[no- ]edit] [-s ] [-X ] [-S[]] [--[no-]rerere-autoupdate] [-m ] [...]
  • ##git merge HEAD ...
  • ##git merge - -abort
  • 1.2 Introduction to git-merge

The git-merge command is used to merge from specified commit(s) to the current branch.

Note: The specified commit(s) here refers to starting from these historical commit nodes until the current separation.

The git-merge command has the following two uses:

is used in git-pull to integrate changes in another code repository (ie: git pull = git fetch git merge)
  1. is used to merge from one branch to another branch
  2. Then the
git merge topic

command will be executed on the master branch The separated nodes (that is, the A B C nodes of the topic branch) after the common node (E node) reappear on the master branch until the current commit node of the topic branch (C node), and is located at the top of the master branch. And create a new node along the master branch and topic branch to record the merge results. This node carries the user's information describing the merge changes.1.3

git merge HEAD ...

CommandThis command exists for historical reasons and should not be used in new versions It should be replaced with

git merge -m ....

1.4

git merge --abort

CommandThis command is only used when conflicts result after merging.

git merge --abort

will abandon the merge process and try to rebuild the pre-merge state. However, if there are uncommitted files when the merge starts,git merge --abortwill not be able to reproduce the pre-merge state in some cases. (Especially when these uncommitted files will be modified during the merge process)

Warning: It is easy to contain a large number of uncommitted files when running
git-merge

You get stuck in a situation that will make it difficult for you to back down in a conflict. Therefore, it is highly discouraged to have uncommitted files when usinggit-merge. It is recommended to use thegit-stashcommand to temporarily store these uncommitted files and use them after resolving conflictsgit stash popRestore these uncommitted files.

2. Parameters

This section is used to introduce the parameters used in the

git-merge

command2.1

--commit The

and--no-commit

--commit

parameters cause a commit node of the merged result to be generated after merging. This parameter can override--no-commit. The--no-commit
parameter causes the merge to not be automatically submitted in order to prevent the merge from failing, giving the user a chance to review and modify the merge result before submission.2.2

--edit

and-eand--no-edit

--edit

and-eare used to call the editor to further edit the automatically generated merge information before successful merge and submission. Therefore, users can further interpret and judge the results of the merger. The--no-edit
parameter can be used to accept automatically merged information (this is generally discouraged).

If you have given the
-m

parameter when merging (described below), use--edit(or-e) is still useful, this will further edit the content contained in-min the editor.

Older versions of nodes may not allow users to edit merge log information.

2.3
--ff

Command

--ff

refers to the fast-forward command. When merging using fast-forward mode, a new commit node will not be created. By default,git-mergeadopts fast-forward mode.For a detailed explanation of the fast-forward mode, please see my other article: "About fast forward" section of a successful Git branch model.
2.4

--no-ff

CommandCreate a new merge node even if fast-forward mode can be used. This is the default behavior when

git merge

merges a tag.2.5

--ff-only

CommandUnless the current HEAD node has been up-to-date (update points to the latest node) or fast-forward mode can be used Merge, otherwise the merge will be rejected and a failure status will be returned.

2.5--log[=]and--no-log

##--log[= ] When merging and submitting, in addition to the branch name, it will also contain the log information of up to n merged commit nodes.
--no-log will not list this information.

2.6

--stat,-n,--no-statCommand

--statThe parameter will display the status of file differences at the end of the merge result. The status of file differences can also be configured in merge.stat in the git configuration file.In contrast, the
-n,--no-statparameters will not display this information.

2.7

--squashand--no-squash

--squashWhen a merge occurs, from The other branch node after the common ancestor node of the current branch and the other branch until the top node of the other branch will be compressed together. The user can submit it after review to generate a new node.

Note 1: This parameter conflicts with

--no-ff

##Note 2: The result after using this parameter is similar to Commit a new node on the current branch. This parameter is very useful in some cases, such as when using Git Flow (about Git Flow, please refer to: A successful Git branch model). When the function branch is developing a functional requirement, the developer may submit a large number of locally. And meaningless nodes, when they need to be merged into the develop branch, you may only need to use a new node to represent the modification content of this long list of nodes. At this time, the
--squash

command will come into play. In addition, if multiple submissions of the feature branch are not trivial but are meaningful, using the--no-ffcommand is more appropriate.--no-squash
has the exact opposite effect.

2.8
-s

and--strategy=##-s < strategy>

and

--strategy=are used to specify the merge strategy. By default, if this parameter is not specified, git will use the default merge strategy according to the following conditions:When the merge node only contains a single parent node (such as when using fast-forward mode), the recursive strategy will be used ( introduced below).

    When the merged node contains multiple parent nodes (such as when using no-fast-forward mode), the octopus strategy (described below) is used.
  1. 2.9
  2. -X
and

--strategy-option=

, specify the specific parameters of the strategy (described below).

2.10--verify-signatures

,

--no-verify-signaturesis used to verify whether the merged node has a GPG signature , and ignore those nodes without GPG signature verification in the merge.(The following quote is taken from a reprinted article. Since I have not found the original author, I cannot provide the original author information and the original link. If there is any infringement, please let me know via private message or comment, and I will delete the following quote.)


GPG is encryption software. You can use the public key generated by GPG to safely spread your files and codes on the Internet.

Why do you say safe? Take the repo developed by Google as an example. The repo uses GPG verification. Each milestone tag has GPG encryption verification. If you want to make changes at milestone v1.12.3, delete the tag after the modification, and then It is definitely possible to create a tag with the same name to point to your modification point. However, when you clone your modified project again, you will find that your changes to this milestone tag are not recognized and the verification fails, causing your modifications to not be implemented normally here. This is the role of GPG verification, which ensures that the milestones set by the project author (private key holder) cannot be modified by others. Then, it can be said that the author's code is safely disseminated.
Why is there such a need? From development to release to later update iterations of a project, there will definitely be a number of stable versions and development versions (there are instability factors). As project initiators and holders, they have the right to define a stable version that they (they) recognize. This stable version will not allow other developers to make changes. Take Google's repo project as an example. The project owner defines point A in the project development process as the stable version v1.12.3. Then after users download the v1.12.3 version, they will definitely use the projects and products generated by point A. Even if other developers can re-specify v1.12.3 locally and specify it to their modified point B, when the modified version is finally used by users, there will be a problem that GPG signature verification fails, that is to say, this is The modification will not take effect.



2.11

—summary
,

--no-summaryand--stat

and

--no-statis similar and will be removed in a future version.2.12-q

and

--quietoperate silently and do not display merge progress information.

2.13

-v

and

--verbosedisplay detailed merge result information.

2.14--progressand--no-progress

switch whether to display the merged progress information. If neither is specified, a message will be displayed on the connected terminal when standard error occurs. Note that not all merge strategies support progress reporting.

2.15-S[]and--gpg-sign[=]

GPG signature.

2.16-m

Set the commit information used when creating merge nodes.
If the--logparameter is specified, the short log of the commit node will be appended to the commit message.

2.17--[no-]rerere-autoupdate

rerere means reuse recorded resolution, reuse the recorded solution. It allows you to ask Git to remember how to resolve a block conflict so that the next time you see the same conflict, Git can automatically resolve it for you.

2.18--abort

Abandon the current merge conflict handling process and try to reconstruct the pre-merge state.

3. Other concepts about merging

3.1 Detection before merging

When merging external branches, you should keep your own branches clean, otherwise there will be merge conflicts. It will cause a lot of trouble.
In order to avoid recording irrelevant files when merging commits, the git-pull and git-merge commands will stop if there are any uncommitted files registered in the HEAD node pointed to by index.

3.2fast-forward merge

Normally branch merge will produce a merge node, but there are exceptions in some special cases. For example, when calling the git pull command to update the remote code, if the local branch does not have any commits, there is no need to generate a merge node. In this case, a merge node will not be generated, and HEAD points directly to the updated top code. This merge strategy is fast-forward merge.

3.3 Merger details

In addition to the fast-forward merge mode mentioned above, the merged branch will be tied to the current branch through a merge node. The merge node will also Have the top node of the current branch before merging and the top node of the other branch, both as parent nodes.
A merged version will make the changes in all related branches consistent, including the commit node, HEAD node and index pointer, and the node tree will be updated. As long as the files in these nodes do not overlap, changes to these files will be modified and updated in the node tree.
If these changes cannot be merged explicitly, the following will happen:

  1. The node pointed to by the HEAD pointer remains unchanged
  2. MERGE_HEADPointer Are placed on top of other branches
  3. The merged clean path is updated simultaneously in the index file and the node tree
  4. For conflict paths, the index file records three versions: version 1 records two The common ancestor node, version 2 records the top of the current branch, that is, HEAD, and version 3 recordsMERGE_HEAD. The files in the node tree contain the results of the merge program. For example, the three-way merge algorithm can cause conflicts.
  5. No other changes have occurred. In particular, local modifications you made previously will remain intact.
    If you tried a merge that resulted in a very complex conflict and want to start over, you can usegit merge --abort

About three-way merge Algorithm:
The three-way merge algorithm is a way to resolve conflicts. When a conflict occurs, the three-way merge algorithm will obtain three nodes: the B node of the local conflict, the C node of the other branch, and the B and C nodes. The common most recent ancestor node A. The three-way merge algorithm will merge based on these three nodes. The specific process is to compare nodes B and C with node A. If a file in node B and C is the same as that in node A, then there will be no conflict; if only one of B or C has changed compared to node A, then The file will adopt the changed version; if B and C have changed compared with A, and the changes are not the same, then you need to merge them manually; if B and C have changed, and the changes are the same, then There will be no conflict and the changed version will be automatically adopted. After the final merger, D node will be generated. D node has two parent nodes, namely B and C.

3.4 Merge tag

When merging a tag, Git always creates a merged commit, even if fast-forward mode can be used at this time. The template of the submission information is preset to the information of the tag. Additionally, if the tag is signed, signature detection information will be appended to the commit message template.

3.5 How conflicts are expressed

When a merge conflict occurs, this part will end with<<<<<<<,========and >>>>>>> represent. The part before =======is the situation on the current branch, and the part after ========is the situation on the other side's branch. >>>>>>>

3.6 How to resolve conflicts

After seeing the conflict, you can choose the following two methods:

  • Decided not to merge. At this time, the only thing to do is to reset the index to the HEAD node.git merge --abortis used in this situation.
  • Resolve conflicts. Git will mark the conflict. After resolving the conflict, usegit addto add it to the index, and then usegit committo generate a merge node.
    You can use the following tools to resolve conflicts:
  • Use the merge tool.git mergetoolwill call a visual merge tool to handle conflicting merges.
  • View the differences.git diffwill display the three-way difference (the three-way comparison algorithm used in the three-way merge).
  • View the differences for each branch.git log --merge -p will display the difference between theHEADversion and theMERGE_HEADversion.
  • View the version before the merge.git show :1:File nameDisplays the version of the common ancestor,git show :2:File nameDisplays the HEAD version of the current branch,git show :3:File nameDisplay theMERGE_HEADversion of the other party's branch.

4. Merge strategy

Git can specify the merge strategy by adding the -s parameter. Some merge strategies even have their own parameter options. Use-Xto set the parameter options of these merge strategies. (Don't forget that merging can happen in both git merge and git pull commands, so this merge strategy applies to git pull as well).

4.1resolve

Only use the three-way merge algorithm to merge the top nodes of two branches (such as the current branch and another branch you pulled down). This merge strategy follows a three-way merge algorithm, where the HEAD nodes of the two branches and the common child nodes perform a three-way merge.
Of course, what really bothers us is the situation of cross-merge (criss-cross merge). The so-called cross-merging refers to the situation where there are multiple common ancestor nodes. For example, when two branches are merged, it is very likely that there are two common ancestor nodes. At this time, the merger cannot be performed according to the three-way merge algorithm (because Common ancestor nodes are not unique). This is how the resolve strategy handles cross-merge problems. Here is a reference to "Version Control with Git":

In criss-cross merge situations, where there is more than one possible merge basis, the resolve strategy works like this: pick one of the possible merge bases, and hope for the best. This is actually not as bad as it sounds. It often turns out that the users have been working on different parts of the code. In that case, Git detects that it's remerging some changes that are already in place and skips the duplicate changes, avoiding the conflict. Or, if these are slight changes that do cause conflict, at least the conflict should be easy for the developer to handle

Here is a brief translation: In the case of cross-merging, there is more than one merge reference point (common ancestor node). The resolve strategy works like this: select one of the possible merge reference points and expect this to be the most merged reference point. good result. This is actually not as bad as it sounds. Usually users modify different parts of the code, in which case many merge conflicts are actually redundant and repetitive. When using resolve to merge, the conflicts generated are easier to handle, and there are very few cases where code will actually be lost.

4.2recursive

Only use the three-way merge algorithm to merge two branches. Different from resolve, in the case of cross merge, this merge method is called recursively. Starting from the different nodes of the two branches after the common ancestor node, the three-way merge algorithm is recursively called to merge. If a conflict occurs, then the file The merge will no longer continue and conflicts will be thrown directly; other files without conflicts will be executed until the top node. Additionally, this approach is able to detect and handle operations involving modification of file names. This is the default merge action for git merging and pulling code.
The recursive merge strategy has the following parameters:

4.2.1 ours

This parameter will force the version of the current branch to be automatically used when a conflict occurs. This merge method will not cause any trouble, and even git will not check the conflict content contained in other branch versions. This method will discard any conflict content in the other branch.

4.2.2 theirs

is exactly the opposite of ours.
Both theirs and ours parameters are suitable for merging binary file conflicts.

4.2.2 patience

With this parameter,git merge-recursiveSpend some extra time to avoid missing unimportant lines (such as functions) brackets). If the version branch separation between the current branch and the other branch is very large, it is recommended to use this merge method.

4.2.3diff-algorithm=[patience|minimal|histogram|myers]

Informationgit merge-recursiveUse a different comparison algorithm .

4.2.4ignore-space-change,ignore-all-space,ignore-space-at-eol

Treat space conflicts according to the specified parameters.

  • If the other party's version only adds changes in spaces, then our own version will be used when the conflict is merged
  • If our version contains spaces, but the other party's version contains a large number of changes, then the conflict will occur Use the other party's version when merging
  • Use the normal process

4.2.5no-renames

Turn off rename detection.

4.2.6subtree[=]

This option is an advanced form of subtree merge strategy, which will guess the process of merging two node trees. How to move in. The difference is that the specified path will be removed at the beginning of the merge, so that other paths can be matched when looking for subtrees. (See below for details on the subtree merge strategy)

4.3octopus

This merge method is used for more than two branches, but it will refuse to merge when conflicts require manual merge. This merge method is more suitable for bundling multiple branches together and is also the default merge strategy for multi-branch merges.

4.4ours

This method can merge any number of branches, but the merged result of the node tree is always the conflicting part of the current branch. This method can be very efficient when replacing older versions. Please note that this method is different from the ours parameter under the recursive strategy.

4.5subtree

Subtree is a modified version of the recursive strategy. When merging tree A and tree B, if B is a subtree of A, B first adjusts to match the tree structure of A instead of reading the same node.

4.5 Summary

When using the three-way merge strategy (referring to the default recursive strategy), if a file (or a line of code) changes in both the current branch and the other branch, but slightly Then it rolls back on one of the branches,then this rollback change will be reflected in the result. This point may confuse some people. This is because during the merge process, git only focuses on the common ancestor node and the HEAD node of the two branches, rather than all nodes of the two branches. Therefore, the merge algorithm will regard the rolled-back part asunchanged, so that the merged result will become the changed part of the other branch.

5. Some personal opinions on the use of Git

I have always believed that Git is a very excellent version control tool, but many people in the company find Git difficult to use. A large part of the reason for this situation is that the inertia brought by the previous use of subversion has an impact on accepting new technologies; on the other hand, many people only use Git through the GUI client. For a long time, most people have thought that using GUI is a more convenient way to get started. In fact, this is questionable. According to my personal experience, using GUI can create inertia, and operations can often be completed by clicking a few buttons, making many people think that learning Git commands is a waste of time and energy. But in fact, without a clear understanding of Git commands and ideas, using those simple buttons will actually cause a lot of trouble: many people have no idea what will happen after clicking the button, and the GUI is too smart to let the same button The click event may correspond to commands with different parameters. In the end, it is the poor users who are really hurt because they have no idea what the problem is.
Based on the content of the full text, here is a summary of some of the conventions that individuals abide by when using Git. The so-called agreement refers to a non-forced and voluntary behavior. Failure to adhere to these conventions will not cause any defects, but complying with these conventions may alleviate difficulties and improve efficiency when using Git.

  1. Submit more and push less. When multiple people collaborate, push will frequently cause merge conflicts, affecting efficiency. Therefore, try to use commit commands as much as possible and reduce the use of merge, which will save a lot of time.
  2. Use Git Flow (Git Flow), see my other article for details: A successful Git branch model
  3. Use branches,Keep the main branch clean. This is something I strongly recommend. Submit on the branch, then switch to the main branch to update (git pull —rebase), then merge the branches and push. Such a process will avoid cross-merging (there will not be multiple common ancestor nodes). In fact, the reason why many people feel overwhelmed by the git merge operation is the cross-merge problem caused by various reasons, which causes some code to be lost during the merge process. Keeping the master branch clean can avoid cross-merges.
  4. Disable fast-forward mode. Use the rebase parameter when pulling code (the premise is to keep the main branch clean), and use the -no-ff parameter to disable fast-forward mode when merging. This can not only ensure the clarity of the node, but also avoid cross-merging. Appear.

Recommended study: "Git Learning Tutorial"

The above is the detailed content of Detailed analysis of git-merge (organized and shared). For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:csdn.net. If there is any infringement, please contact admin@php.cn delete