preface

One of the biggest uses of Git, besides its ability to manage individual projects, is for collaborative team development. Moreover, Linus developed Git to maintain the Linux kernel as an open source project. Therefore, it is important to familiarize yourself with the general steps and methods for collaborative multi-party development using Git. This tutorial will introduce you to a general approach to collaborative team development with Git and how to resolve common problems with Git pull operations.

A,gitCollaborative way

1. Common development patterns

  • Gitflow: Simply put, it is a general term for multiple development patterns. For example: how many branches to use, when to merge branches, etc. This aspect is longer, more content, and will be explained in detail later;

  • Git branch based development model: Generally at least three branches:

    • developBranches: Frequently changing branches for collaborative development, file pushing, and merging among developers;
    • testBranch: a branch used by testers, products, etc., that does not change very frequently;
    • masterBranch: production release branch, a branch that changes very infrequently (usually with permissions set because it is directly related to production);
    • bugfix(hotfix)Branch: a branch used for emergency repair; When there is an emergencybugWhen in the conventionaldevelopBranch fixes are too late. In this case, you can just call itmasterThe branch code is pulled tobugfixOn the branch, proceedbugFix it, and when you’re done, merge it intomasterPublish on the branch;

    Develop -> test -> master

2.SVNMode (typical model)

First, there are two users A and B. A’s local warehouse is not empty, B’s warehouse is empty, and there is A remote warehouse C.

  • A firstly pushes the code of the local warehouse to C. At this time, the files of A and C are consistent, as shown in figure 1.

  • Then B pulls down the code of C, as shown in Figure 2. At this time, the files in warehouses A, B and C are consistent. Subsequently, A and B continued to develop locally and submitted several times to their local warehouses.

  • At this point, A first pushes the modified local repository file to C. Since this is the first modification of remote repository C, all files in C are in A, so it can be directly pushed without first executing Git pull, as shown in Figure 3.

  • Later, an error occurs when B pushes the modified local repository file to C. The reason is as follows: at this time, C has the modification made by A, so B cannot overwrite it. In order for B to push it successfully, it should first pull the file from C to the local. As shown in Figure 4, there are two situations when pulling:

    • successful:AwithBThe modified files are not the sameFast-forwardMode automatic merge;
    • failure:AwithBModify the same file, need to manually resolve the conflict and merge;
  • After B successfully pulls the files from C to the local repository and merges them, the changes made by B to the local repository can be pushed to the remote repository C, as shown in figure 5.

In the whole process, it can be found that remote repository C only plays the role of third-party hosting code;

3. Simulate multiplayer collaboration

To simulate multi-user collaboration, use –local to set user information for each warehouse:

git config --local user.name 'Joe'
Copy the code

–local is a scoped parameter.

  • --global: applies to each computer user and has the second priority.
  • --system: applies to the entire system and has the lowest priority.

Git Clone: Git clone: git clone: git clone

You can also rename the remote repository file downloaded locally by following the link with a string:

git clone [email protected]:ahuntsun/MY.git mygit2
Copy the code

4. Nature of collaboration

A remote repository usually has multiple branches, and instead of pushing all branches of the local repository to the remote repository in a single push, one branch of the local repository is selected and pushed to one of the branches of the remote repository:

For example, the local master branch, as shown in the figure above, can select one of the remote repository’s master, dev, and test branches to push. If you want to push to the master branch of the remote repository, if there is no connection between the two branches at first, you will need to:

  • (1) Establish local firstmasterBranch and RemotemasterBranch associations (more on how to establish associations in the next section);
  • ② Through the localmasterBranch and RemotemasterThe merging of branches synchronizes the contents of the two branches for the first time.
  • (3) in the localmasterChanges are made on the branch and pushed to the corresponding remotemasterBranch. At this point, the contents of the two branches are synchronized for the second time.

Second,git pull

In the actual development, before pushing the code, it is often necessary to perform a Git pull to pull the code from the remote repository to the local and merge it. Git pull = git fetch + git merge

  • git fetch: indicates that all files in the remote repository are pulled to the local version library.
  • git merge: Merges files in the remote repository with files in the local repository.

However, when executing git pull commands, there are often various merge errors due to the difference between the local and remote repositories’ historical commit records. Before analyzing these errors, set up the test environment:

Create two local repositories, mygit and mygit2, and associate them with the same remote repository, as shown below:

1. No merge conflict occurs

Configure the new user LISi in the local repository mygit2 with the –local parameter to simulate multi-person collaboration, and then push a new file to the remote repository via LISI. Go back to mygit and run git remote show origin.

Mygit2 > mygit > mygit > mygit > mygit > mygit > mygit > mygit Git pull = mygit pull = mygit pull = mygit pull = mygit pull = mygit

The second arrow in the figure shows that the master branch in MyGit and the master branch in the remote repository were merged in a fast-forward manner and synchronized during the pull operation.

The local remote branch origin/master represents the remote master branch, which will be explained in more detail in the next section;

aboutFast-forwardThe approach was introduced earlier, in the above merger processorigin/masterThe branch points directly to the latest commit, with no other branches in between and no merge conflicts. This merge method is calledFast forward. As shown below:

This is an ideal situation, because in many cases when git pull is performed, merge conflicts will occur and need to be resolved before manual merge is performed.

2.git pullHomologous merge conflict

The so-called homology means that branches in the local warehouse and remote warehouse share the same commit history starting from the root commit node. In short, two branches that have a common root commit node are called homologous; As shown in the figure below, the master branch in both repositories has A common root commit node A, so the master branch in both repositories is homologous:

Git pull fails to automatically merge with the develop. TXT file.

Auto-merging develop.txt
CONFLICT (content): Merge conflict in develop.txt
Automatic merge failed; fix conflicts and then commit the result.
Copy the code

The reason for the error

The specific situation is simulated as follows:

In mygit, modify the second action 1 of hello. TXT file, and in mygit2 modify the second action 2 of hello. TXT file, that is, modify the same place of the same file.

At this point, it depends on who does git push first. If mygit pushes the modified hello. TXT to the remote repository first. So when mygit2 pushes again, the following error will appear:

There are some files in the remote repository that you do not have, so you cannot update the remote repository. This is because myGit first pushes the modified hello.txt to the remote repository; In order for mygit2 to push successfully, it is necessary to merge the hello. TXT modified by mygit in the remote repository with the hello. TXT in the local repository.

The solution

Git pull can be used to solve this problem, so let’s do a Git pull operation first:

Git pull fails to merge automatically because mygit and mygit2 have both changed the same place in hello.txt. Git does not know which one to use, so automatic merge fails.

The first step:

Open the conflict file hello. TXT and you can see the typical display of the conflict file:

The arrows <<< and >>> indicate the location of the conflict. 2 is mygit2’s modification of hello. TXT, 1 is the contents of hello.

After negotiation, leave the third line and delete the rest:

This resolves the conflict by manually merging the changes to the file hello.txt.

Vim instruction added: After entering the command line mode through ESC, select a line through the up and down arrow key, and then double-click D to delete the line where the cursor is; To delete multiple lines, enter 2,4d to delete lines 2 to 4.

The second step:

Check the status again:

Hello. TXT is in the workspace and git prompts us to add the changes we made to hello. TXT while resolving the conflict to the staging area with git add.

Step 3:

aftergit addAfter that, commitgit commit

Thus, the conflict is resolved;

As you can see from the arrow in the figure above, the master branch in mygit2 has committed twice more than the Origin/Master branch. Since the Origin/Master branch represents the master branch of the remote warehouse, that is, the master branch in mygit2 is two commits ahead of the master branch of the remote warehouse; The process is shown in the figure below:

  • First of all,mygitWhen submitting1stBased on the carried out the no2Times commit (modifyhello.txtAfter the),mygitPush the local repository (push) to the remote warehouse;
  • At this timemygit2A commit is also made in the local repository3rd(modifiedhello.txt), there will be an error when pushing to the remote warehousepullOperation;
  • whenmygit2performpullOperation to pull the remote warehouse to the local, due to a conflict, so will not temporarilyorigin/masterUpdate the pointer to the latest commit; Then, inmygit2After manual decontaminating and merging,mygit2Is:

You can see that mygit2 has updated its commit twice since the conflict was resolved, and the Origin /master is still pointing to commit 1st.

So after the conflict is resolved, the Master branch in Mygit2 commits twice before the Origin/Master branch; After git push again, the Origin/Master branch will point to commit point 4th, with the status of the three repositories as follows:

In the actual development, it is inevitable that more than one person will modify the same file. In the process of manual merge, we must negotiate with each other how to merge, rather than directly overwrite.

3.git pullMerge conflicts between different sources

By different sources, we mean branches in two repositories with different root submission nodes, as shown in the following figure:

Suppose the local master branch wants to push content to the remote master branch. The root commit node of the local master branch is 1st, and the root commit node of the remote master branch is A, so the two branches have no common parent commit node. Therefore, there is no merging. Git pull causes the following error:

There is no tracking information for the current branch.
Please specify which branch you want to merge with.
Copy the code

Special case: If the local repository mygit is empty, different source merge conflicts can also occur.

The reason for the error

In short, there are two reasons for the failure of Git pull:

  • First point: The Master branch in the two repositories has no common commit history due to the different root commit nodes. Therefore, when branches are merged using the three-party merge principle, the common commit node cannot be found and therefore cannot be merged:

  • ** Second point: ** localmasterThe branch is not associated with any branch in the remote repository. Therefore, localmasterThe branch doesn’t know who to push the file to, so it naturally fails;

The solution

Given the two reasons for git pull’s failure, the solution is clear, again in three steps:

  • ** Step 1: ** Perform a git pull to pull the branch from the remote repository to the local repository:

    The local remote branches origin/master and origin/dev here are the local forms of the remote branches master and dev, representing them and content consistent with them. Although git pull failed, we got the information of the remote branch, which is convenient for the second step merge operation.

  • ** Step 2: ** Create a public commit history for both branches. In this case, the two branches do not have a common parent node and cannot be merged in merge mode. You should use rebase to append the local master branch to the remote master branch. Since the local remote origin/master branch has the same commit history as the remote Master branch, we can write:

    git rebase origin/master
    Copy the code

    At this point, the commit history of the local master branch becomes A < -b < -1st < -2nd. The local master branch and the remote Master branch have a common commit history.

    Short: You can combine the first and second steps into a single operation using arguments:

    git pull --rebase origin master
    Copy the code

  • Step 3: Associate the local master branch with the remote Master branch. The following three methods are commonly used:

    • A:
    / / format
    git branch --set-upstream-to=origin/<branch> master
    // This is the way it works
    git branch --set-upstream-to=origin/master master
    Copy the code

    Git branch -vv git branch -vv git branch -vv git branch -vv

    • \

    Then you can push it:

    • Method 2:
    git push -u origin master
    Copy the code

    This command is used to establish a connection between the local master branch and the remote master branch.

    • Three:
    git push --set-upstream origin master
    Copy the code

    Create a connection between the local master branch and the remote master branch.

Practical demonstration

  • Create two repositoriesmygitAandmygitB, first of all, inmygitAIn themasterAdd on branchA.txt, the submitted information is denoted asA:

  • inmygitACreate and switch todevBranch, add fileC.txtAnd submit the information asC:

  • Switch back to themygitAthemasterBranch, add fileB.txtAnd submit the information asB:

At this time`mygitA`The states of the two branches are as follows:Copy the code

  • Then, establish the association between the local repository mygitA and the remote repository:

  • Set and push mygitA’s master and dev branches to remote repository’s Master and dev branches:

  • Go back to mygitB, add the files 1st. TXT and 2st.txt and commit 1st and 2nd twice:

At this time, the state of the three warehouses is:

If you want to push the master branch of mygitB to the master branch of the remote repository, you can do this in two steps, using shorthand form as discussed above:

  • ** Step 1: ** passesrebaseMerge the localmasterBranch and RemotemasterBranches:
git pull --rebase origin master
Copy the code

After executing the above instructions, the state of mygitB is:

  • ** Step 2: ** create a localmasterBranch and RemotemasterBranch links and push:
git push -u origin master
Copy the code

As shown in the figure, the remote branch is connected and the push is completed; This resolves conflicts of pull operations caused by different sources.