Welcome to github.com/hsfxuebao/j… , hope to help you, if you feel ok, please click on the Star
preface
Git provides the concept of sub-libraries, as a medium to large project often relies on several modules. These submodules can be stored in different repositories, nesting repositories through subModules or subtrees. This is the penultimate lecture of Git application details, victory is not far away!
A, submodule
5. Submodule refers to the introduction of a repository as a submodule into another repository:
1. Import sublibraries
Run the following command:
Git subModule add Sub-library address Save directory
Such as:
Git submodule add [email protected]:AhuntSun/git_child.git mymodule copies the codeCopy the code
The preceding command will save the remote repository corresponding to the address as a sub-library in the myModule directory of the current version library:
Then check the status of the current version library:
You can see that two files have been added. Check out the.gitmodules file:
You can see the path to the current file and the URL of the submodule, and then add, submit, and push the two new files. There are two additional files in the remote repository corresponding to the current repository git_parent:
Where 3bd7f76 in myModule corresponds to the latest commit in the child repository git_child:
Clicking on the MyModule folder will automatically redirect you to the sub-repository:
From the above analysis, it can be concluded that the two repositories have been associated, and the repository git_child is a child of the repository git_parent;
2. Change with the same steps
When the dependent child library changes: add the file world.txt to the child library git_child and submit to the remote repository:
How does the parent library git_parent, which relies on it at this point, sense this change?
Methods a
Git_parent only need to enter the store at this time the child library mymodule git_child directory, execute the git pull to subversion repository git_child update pull to the local:
Method 2
If the parent library git_parent depends on multiple child libraries that have changed, you can iterate through and update all the child libraries as follows: First, go back to the home directory of the repository and execute the following command:
Git submodule foreach Git pullCopy the code
This command iterates through all the child libraries that the current repository depends on and pulls their updates to the parent repository git_parent:
After the pull is completed, check the status and find that the files in the myModule directory have changed, so you need to perform an add, submit, push operation:
3. Copy the parent repository
If you use submodule to add the parent library git_parent that depends on the child library, clone it locally. In the git_parent2 clone, the parent repository of the dependent child repository is present, but the contents are not:
Git_parent2 = git_parent; mymodule = git_parent;
** Solution: ** can use a step operation of multiple commands, or use parameters to combine multiple steps.
Step by step operation
This is an additional operation after the Clone operation, and two things need to be done:
-
Initialize subModule manually:
Git submodule init Copies the codeCopy the code
-
Manually pull dependent subversion libraries; :
Git submodule update -- copying code recursivelyCopy the code
After two steps, there is content in the subversion library. Thus, the clone of git_parent is completed.
merge
Step operations are complicated. You can add parameters to combine multiple steps. Clone a copy of git_parent3 based on git_parent with the following command:
Git clone [email protected]:AhuntSun/git_parent. Git git_parent3 --recursiveCopy the code
–recursive cloning of all child libraries that git_parent depends on.
4. Delete the sub-version library
Git does not provide commands to delete submodule libraries directly, but we can do this through a combination of other commands in three steps:
-
Remove subModule from repository:
Git rm --cache myModule copies the codeCopy the code
Git rm deletes files from the repository and adds this operation to the staging area.
- will
submodule
Delete from workspace;
- The final will be
.gitmodules
Directory deletion;
After completing the three steps, add, submit and push the sublibrary to complete the deletion operation:
Second, the subtree
1. Introduction
Subtree and SubModule function is the same, but subtree appeared later than subModule, it is to make up for the problem of submodule:
- The first:
submodule
You cannot modify the child library code in the parent library, only in the child library, is one-way; - The second:
submodule
There is no direct ability to delete sub-libraries;
On the other hand, subtree can implement bidirectional data modification. The official recommendation is to use subtree instead of SubModule.
2. Create a sublibrary
Git subtree: git_subtree_parent: git_subtree_child: Git_subtree_parent: Git_subtree_child: Git_subtree_parent
3. Build relationships
First we need to add a child library to git_subtree_parent:
** Add the remote address of the sublibrary:
Git remote add subtree-origin [email protected]:AhuntSun/git_subtree_childCopy the code
Once added, there are two remote addresses in the parent repository:
Here subtree-Origin represents the address of the remote repository git_subtree_child.
** Step 2: ** Establish dependencies:
Git subtree add --prefix=subtree subtree-origin master --squash git subtree add --prefix=subtree --p subtree or --prefix subtree replicates the codeCopy the code
This command is used to clone files from the master branch of subtree origin to the subtree directory.
Subtree origin = subtree origin = subtree origin = subtree origin = subtree origin You can switch to another branch and repeat the above operation, which means that the child library is essentially a child branch.
— Squash is an optional parameter, which means to merge and squash.
- If this parameter is not added, the branch specified in the remote sublibrary (here is
master
Commits are pulled locally one by one to create a merge commit; - If this parameter is added, multiple commits on the specified branch of the remote sublibrary will be consolidated into a single commit and pulled locally, so that all historical commits on the specified branch of the local remote sublibrary will be removed.
Subtree = subtree; subtree = subtree; subtree = subtree;
Take a look at the commit history of the parent repository:
The –squash parameter compacts his commit into a single commit, which is merged and committed by the parent library. So there are two more commits in the parent repository.
We then make a push in the parent repository:
As a result, there is an additional subtree directory in the remote repository that holds the child repository files, and it is completely separated from the git_subtree_child directory and is only a directory belonging to the parent repository git_subtree_parent directory. Instead of a pointer that automatically jumps to dependent sublibraries, as with subModule:
subtree
Remote parent repository for:
submodule
Remote parent repository for:
That is, the difference between subModule and subtree sublibrary is:
4. Change with the same steps
Create a new file world in the sublibrary and push it to the remote sublibrary:
Update the content of the dependent child library in the parent library with the following command:
Git subtree pull --prefix=subtree subtree-origin master --squash Copy codeCopy the code
Take a look at the commit history at this point:
Find no sublibrary commit information, this is a –squash effect. Changes to the child library are committed by the parent library.
5. Parameters, squash
This parameter prevents commit history from contaminating the parent repository on the specified branch of the child repository. For example, three commits are made on the master branch of the sublibrary: A, B, and C, and pushed to the remote sublibrary.
First, let’s review the three-way merge rules for merging branches:
When commit 4 and 6 need to be merged, Git will first look for the common parent commit node of both, as shown in figure 2, and then merge 2, 4, and 6 based on commit 2 to get Commit 7.
If you add –squash, the three commits on the master branch of the remote sublibrary are merged into a new commit ABC. It then merges with the master branch of the parent repository neutron library to produce another commit X. The entire pull process produced a total of five commits, as shown below:
Existing problems:
Squash squash squash squash squash squash squash squash squash squash squash squash squash squash squash squash squash squash There are also additional problems with push operations.
Best practice: Either use all operations--squash
Instruction, or do not use this parameter at all, so there is no error.
Wrong example:
To verify, recreate two repositories, A and B, and set B as A sublibrary of A via subtree. This time without using the –squash parameter, repeat:
-
First, modify the sublibrary file;
-
Then, pull the files changed by remote sublibrary A locally without using the –squash command:
Git subtree pull –prefix=subtree subtree-origin master copy code
View the commit history at this point:
It can be seen that the child library’s commit information contaminates the parent library’s commit information, which verifies the above conclusion.
So either use it all or none to avoid errors; If sublibrary commit logs are not required, the –squash command is recommended.
Echo ‘new line’ >> test. TXT: indicates to append text new line to the end of test. TXT file. If it is a >, it replaces all contents in test. TXT.
6. Modify the sublibrary
The power of subtree is that it can modify dependent child repositories in the parent repository. The following is a demonstration:
Go to the subtree directory of the parent repository, modify the child library file child-.txt, and push it to the remote parent repository:
The subtree directory where the child files are stored in the remote parent repository has changed, but the independent remote child repository git_subtree_child has not changed.
-
Modify independent remote sublibraries:
You can run the following command to modify the remote subrepositories synchronously:
Git subtree push --prefix=subtree subtree-origin master copy codeCopy the code
As shown in the following figure, the contents of child2 are synchronized to a separate remote child library:
-
Modify a standalone local sublibrary:
Go back to the local sublibrary git_subtree_child and pull the changes made by the corresponding remote sublibrary to the local for merge synchronization:
As a result, both remote and local sublibraries are modified.
In fact, with subtree, it looks like the parent and child repositories are a whole repository from the outside. When clone is performed, it does not need to iterate through sublibraries to clone individually, as subModule does. Instead, the entire parent repository and its dependent child libraries can be cloned as a whole.
Existing problems
The parent library will update the remote child library for synchronization.
-
First modification of sub-warehouse:
After the preceding operations, the files of the local and remote sublibraries are synchronized. The content of the child. TXT file is child~4. Add child5~6 to this file from the local library:
It is then pushed to a remote sublibrary.
-
Parent warehouse first pull:
The parent repository then pulls the remote child library to synchronize with the child library in the local parent repository git_subtree_parent with the following command:
Git subtree pull --p subtree subtree-origin master --squash Copy codeCopy the code
As a result, the merge failed:
We look at the files generated by the conflict:
It is found that there is no conflict between the child library in the parent version library and the remote child library, but there is a conflict. Why?
Before exploring the causes of conflicts, we first resolve them and delete the redundant content:
Git add and git commit resolve the conflict:
Git doesn’t think we’ve resolved the conflict when we push the file to a separate remote sublibrary:
-
Second modification of child warehouse and second pull of parent warehouse:
Modify the file of the local sub-library again and push it to the corresponding remote repository. The parent version library pulls the updated file of the remote sub-library to the local for synchronization again:
This time it worked! Why does the same operation sometimes succeed and sometimes fail?
The solution
The reason appears in the –squash directive. In fact, the –squash directive merges the commit information in the sublibrary, causing the parent repository to fail to find the common parent node during git pull, resulting in merge conflicts even if the file has no conflicting content. This problem can also occur without –squash, and the root cause of the problem is that no common parent can be found during a three-way merge. We open gitk:
It is not difficult to see from the figure that when subtree is used, there is no public node between the child library and the parent library, so the merge conflict often occurs because the public node cannot be found. At this time, you only need to resolve the conflict and manually merge.
When subtree is not used, branches in a normal repository always have a common node:
** Again: ** Be careful with the –squash directive, use it all or none.
7. Ion extraction library
git subtree split
When some sublibrary comes up during development that can be fully reused in other projects, we want to separate it out.
- ** Method 1: ** Manually copy the file. The disadvantage is that the commit record for the child library is lost;
- ** Method two: ** use
git subtree split
Directive, which logs every commit about a separate child library. However, there are drawbacks:-
For example, the standalone sublibrary is company.util, when both company.util and company.server sublibraries are modified in a single commit.
-
Util, a sublibrary isolated from the above command, only records the commit to its own changes, but not to company.server, so that the commit appears to be only util, which is incomplete.
-
Reference: juejin. Cn/post / 684490…