This is the 15th day of my participation in Gwen Challenge

As the most powerful code management tool in the world, Git is probably familiar to everyone, but as far as I know, there are a lot of people stuck in clone, commit, pull, push… Rebase rebase rebase rebase rebase

Catch a version rollback? Don’t ask me how I know. Just ask, “I used to be.”

In view of these problems, today I will share the cognition and understanding of Git in the past few years, as far as possible to explain Git from the essence, to help you understand the underlying principle of Git step by step, I believe that after reading this article you can change a posture, more coquetted use Git commands.

1. Basic concepts

1.1 Advantages of Git

Git is a distributed code management tool. Before discussing distribution, it is necessary to mention what a centralized code management repository is:

  • Centralized: All code is kept on a central server, so commits must rely on the network and each commit is brought to a central repository. Collaborative development can frequently trigger code mergers, increasing the cost and expense of commits. The most typical example is SVN.

  • Distributed: Submits locally, does not depend on the network, and automatically backs up each submission to the local server. Each developer can clone a copy of the remote repository and bring the commit history with them. Git stands for Git.

What are the advantages of Git over SVN?

For example: “I’m writing a bunch of code and I want to go back an hour or so.” Git’s advantages are obvious because the cost of committing is small and all commit records are kept locally and can be rolled back at any time.

That’s not to say SVN can’t do this, but Git’s fallback is much more elegant. Git has many other advantages over centralized tools, which are not listed in detail.

1.2 File Status

Git files can be divided into three states: Modified, staged, and Committed.

  • Modification: Git can sense which files have been modified in the working directory and add the modified files to the Modified section

  • Staging: Use the add command to commit the modified files in the working directory to the staging area until they are committed

  • Commit: Commit the staging file to the Git directory for permanent storage

1.3 commit node

For the sake of presentation, I’ll use the node name COMMIT for this article

In Git, each commit generates a node, and each node has a hash value as a unique identifier. Multiple lifts form a linear node chain (regardless of the merge case), as shown in figure:

Above the node is the hash calculated by SHA1

C2 contains C1 submissions, and C3 contains C1 and C2 submissions

1.4 the HEAD

HEAD is a very important concept in Git. You can call it a pointer or a reference. It can point to any node and the node it points to is always the current working directory, in other words, the current working directory (the code you see) is the node that HEAD points to.

As an example in Figure 1-1, if HEAD points to C2, the working directory corresponds to C2 node. The details of how to move the HEAD point will be covered later, but don’t get bogged down here.

HEAD can also point to a branch, indirectly to the node that the branch points to.

1.5 Remote Warehouse

Although Git keeps the code and history locally, it ultimately commits to a remote repository on the server. Using the clone command, you can download the code of the remote repository to the local, and synchronize the status of the submission history, branch, HEAD and other states to the local. However, these states are not updated in real time and need to be manually pulled from the remote repository. As for when and how to pull, the following chapters will explain.

With the remote repository as an intermediary, you can collaborate with your colleagues to develop new features and submit them to the remote repository. You can also pull your colleagues’ code from the remote repository.

Note:

Because you and your colleagues are benchmarked against remote repository code, always ensure that remote repository code is of good quality and never commit untested code to the remote repository

Branch of 2.

2.1 What is a branch?

Branch is also a very important concept in Git. When a branch points to a node, the content of the current node is the content of the branch. Its concept is very similar to HEAD and can also be regarded as a pointer or reference. Often different branches are created based on function or version.

So what’s the use of branching?

Here’s an example: Your App went through a lot of difficulties and finally released v1.0 version. Due to urgent demand, we started v1.1 without a stop after v1.0 was launched. When your development was on the rise, QA students said that users gave feedback on some bugs and needed to fix them and re-issue the version. Fixing V1.0 will definitely be based on V1.0 code, but you’ve already developed part of V1.1.

The above problems can be solved elegantly by introducing the concept of branching, as shown in Figure 2-1

First look at the diagram on the left. Assume that C2 node is the v1.0 version code, and create a branch FT-1.0 based on C2 after it goes online

Look at the diagram on the right. V1.1 content can be developed in master branch after v1.0 is launched. V1.1 code generation node C3 can be submitted after receiving feedback from QA students, and then it is switched to FT 1.0 branch for bug fixing. Then switch to the Master branch and merge the FT-1.0 branch, where we solve the above problem

In addition, there are many things you can do with branches. For example, if you have a requirement that is not sure whether to go live or not, you can create a separate branch to develop this feature. When you need to go live, you can merge it into the main branch. There are too many scenarios for branches to list.

Note:

When a branch is created on a node, the code corresponding to the node is not copied out, but the new branch points to the node, so the space overhead can be greatly reduced. Keep in mind that both HEAD and branch are just references, very light in magnitude

3 Command description

3.1 Submission Related

As mentioned earlier, to commit code, you must first add it to the staging area, which in Git is done with the command add.

Add a file to the staging area:

Git add Specifies the path to the git fileCopy the code

Add all files to staging area:

git add .
Copy the code

Git also provides commands to undo workspaces and staging areas

Undo workspace changes:

Git checkout -- file nameCopy the code

Empty temporary storage area:

Git reset HEAD File nameCopy the code

Commit:

After adding the modified file to the staging area, you can submit it. After submitting, a new submission node will be generated. The specific command is as follows:

Git commit -mCopy the code

3.2 Branch correlation

Create a branch

Create a branch that points to the same node as HEAD. The new branch points to the same node as HEAD.

Git branch Specifies the branch nameCopy the code

Switch branch

When the branch is switched, by default the HEAD points to the current branch, meaning that the HEAD indirectly points to the node that the current branch points to

Git Checkout branch nameCopy the code

Alternatively, you can create a branch and switch immediately.

Git checkout -bCopy the code

Delete the branch

To keep the repository branch simple, a branch should be removed when it has completed its mission. For example, as mentioned above, open a separate branch to complete a function. When this function is merged into the main branch, the branch should be deleted in time.

The delete command is as follows:

Git branch -d Specifies the branch nameCopy the code

3.3 Merge Correlation

The merge command is the most difficult to master and the most important. There are about three merge commands, merge, rebase, and cherry-pick

merge

Merge is the most common merge command, which merges code from a branch or node into the current branch. Specific commands are as follows:

Git merge branch name/node hashCopy the code

If the branch to be merged is ahead of the current branch, as shown in Figure 3-1

Git merge FT-1 will trigger a fast forward after ft-2 executes git merge FT-1. In this case, both branches point to the same node, which is the ideal state.

However, in actual development, we often encounter the following situation: Figure 3-2(left)

After git merge ft-1, git merges C3 and C4 into C5, and finally points FT-2 to C5, as shown in Figure 3-2(right)

Note:

If C3 and C4 change the same line of code in the same file at the same time, the merge will fail because Git doesn’t know which node to base it on, so you will need to merge the code manually

rebase

Rebase is also a merge instruction, with the following command line:

Git rebase branch name/node hashCopy the code

Unlike merge, a Rebase merge does not appear to create new nodes (it does, just a copy is made), but instead directly sums the nodes that need to be merged, as shown in Figure 3-3

In ft-1.0, git rebase master will copy the C4 node after C3, i.e. C4′, which corresponds to C4′, but the hash value is different.

Rebase is more linear and clean than merge commit history, making parallel development flows look serial and more intuitive. Now that Rebase is so good, can you abandon merge? Not really. Here are some advantages and disadvantages of Merge and Rebase:

Advantages and disadvantages of Merge:

  • Advantages: Each node is arranged in strict chronological order. When a merge conflicts, only the nodes to which the two branches point need to be resolved

  • Disadvantages: Merging two branches will most likely generate new nodes and forks, resulting in a messy commit history over time

Advantages and disadvantages of Rebase

  • Advantages: Makes the commit history look more linear and clean

  • Cons: While the commit looks linear, it’s not really chronological, as in Figure 3-3, it ends up behind C3 whenever C4 is committed before or after C3. And when merge conflicts occur, it is theoretically possible to have several nodes rebase to the target branch to handle several conflicts

The author does not agree with some views of using only Rebase on the network. If different branches merge and use Rebase, they may need to resolve conflicts repeatedly, which is not worth the loss. However, rebase is preferred if it is pushed locally to remote and corresponds to the same branch. So my idea is to use merge and Rebase properly for different scenarios, and use Rebase first if you think it works

cherry-pick

Cherry-pick is different from Merge and Rebase. You can select several nodes to merge, as shown in Figure 3-4

The command line:

Git cherry-pick Node hash valueCopy the code

Git cherry-pick C3(hash) git cherry-pick C4(hash)

3.4 Rollback Related

The separation of the HEAD

By default, the HEAD points to a branch, but it is possible to detach the HEAD from the branch and point directly to a node by using the following command:

Git checkout --detachCopy the code

Git also provides a relative reference command for HEAD to point directly to the previous node or N nodes based on a particular location (branch /HEAD) :

Git checkout () {// git checkout () {// git checkout () {// git checkout () {// git checkout ()Copy the code

What’s the use of separating the HEAD and pointing to a node? For example, if you find a problem with the previous commit, you can point your HEAD to the corresponding node and commit after modification. You don’t want to create a new node, but just add –amend. The command is as follows:

git commit --amend
Copy the code

The fallback

If you write a lot of code and then submit it, you will find that there is something wrong with the code, so you want to return the code to the previous submission.

Git reset HEAD~NCopy the code

Reset is similar to a relative reference, except that it reverses both the branch and the HEAD.

3.5 Remote Correlation

When working on a new project, the first thing you need to do is to remove the code. With Git, you can clone a copy of the code from a remote repository.

Git Clone repository addressCopy the code

As I mentioned in the previous section, Clone not only copies code, but also removes references to remote repositories (branches/heads) and saves them locally, as shown in Figure 3-5:

Origin /master and Origin/FT-1 are branches of the remote warehouse, and these reference states of the remote warehouse will not be updated to the local in real time. For example, if the origin/ Master branch of the remote warehouse adds a submission, the local will not be aware of it. So the local Origin/Master branch still points to the C4 node. We can manually update the remote warehouse state with the fetch command

Tip:

You can clone a local repository as a remote repository. Of course, it is not possible to clone a local repository as a public repository in real development. This is simply to help you understand the distribution more clearly

fetch

In simple terms, the fetch command is a download operation, which downloads the status of the remote newly added node and reference (branch /HEAD) to the local device as follows:

Git fetch Remote repository address/branch nameCopy the code

pull

The pull command can pull code from a reference in a remote repository as follows:

Git pull Name of the remote branchCopy the code

The essence of pull is fetch+merge, which first updates all the state of the remote repository to local and then merges it. After the merge is complete, the local branch points to the latest node

In addition, the pull command can be merged using rebase as follows:

Git pull --rebase the remote branch nameCopy the code

push

The push command can push a local commit to a remote commit.

Git push remote branch nameCopy the code

If you push directly, you may fail because there may be conflicts, so you usually pull before pushing, and if there are conflicts, you resolve them locally. After the push succeeds, the local remote branch reference is updated to point to the same node as the local branch.

3 To sum up

  • Both heads and branches are just references, and reference + nodes are key to Git’s distribution

  • Merge has a more specific time history than Rebase, which makes the commit more linear and should be preferred

  • You can view the code for each commit by moving the HEAD

  • Clone or FETCH stores all commits and references to the remote repository in a local copy

  • The essence of pull is fetch+merge, which can also be added –rebase merges by rebase