Git study notes

Git common syntax

[TOC]

Introduction to Git

describe

Git (pronounced / g) ɪ t/. ) It is an open source distributed version control system, which can effectively and quickly deal with the version management of projects from very small to very large. Git is an open source version control software developed by Linus Torvalds to help manage Linux kernel development.

Torvalds started developing git as a transitional solution to replace BitKeeper, which has been the main source code tool used by Linux kernel developers around the world. Some people in the open source community felt that BitKeeper's license was not suitable for the work of the open source community, so Torvalds decided to start studying a version control system with more flexible license. Although git was originally developed to assist the Linux kernel development process, we have found that Git is also used in many other free software projects. For example, many Freedesktop projects have been migrated to GIT.

characteristic

The biggest difference between distributed and centralized is that developers can submit to the local. Each developer copies a complete Git warehouse on the local machine through git clone.

The following figure shows the classic git development process.

git process

Git features:

From the perspective of ordinary developers, git has the following functions:

1. Clone the complete Git warehouse (including code and version information) from the server to a single machine.

2. Create branches and modify code on your own machine according to different development purposes.

3. Commit code on your own branch.

4. Merge branches on a single machine.

5. fetch the latest version of the code on the server and merge it with your main branch.

6. Generate a patch and send the patch to the main developer.

7. According to the feedback from the main developer, if the main developer finds a conflict between two general developers (the conflict they can solve together), he will ask them to solve the conflict first, and then submit it by one of them. If the main developer can solve it by himself or there is no conflict, it can be passed.

8. Generally, developers can use the pull command to resolve conflicts. After resolving conflicts, they can submit patches to the main developer.

From the perspective of the main developer (assuming that the main developer does not need to develop code), git has the following functions:

1. Check email or other ways to check the submission status of general developers.

2. Patch and solve the conflict (you can solve it yourself, or ask developers to solve it and resubmit it later. If it is an open source project, you have to decide which patches are useful and which are not).

3. Submit the results to the public server and notify all developers.

advantage:

fit Distributed development , emphasizing the individual.

Public server pressure and data volume will not be too large.

Fast and flexible.

Conflicts can be easily resolved between any two developers.

Work offline.

Disadvantages:

There are few materials (at least there are few Chinese materials).

The learning cycle is relatively long.

Not in line with conventional thinking.

The confidentiality of the code is poor. Once the developer clones the whole library, all code and version information can be fully disclosed.

Workflow

The general workflow is as follows:

  • Clone Git resource as working directory.
  • Add or modify files on cloned resources.
  • If someone else changes it, you can update the resource.
  • View changes before submitting.
  • Submit changes.
  • After the modification is completed, if an error is found, the submission can be withdrawn and modified and submitted again.

The following figure shows the workflow of Git:

it-proces

Install Git

Installing git on linux

yum -y install git

Installing git on mac

One is to use homebrew to install git.

brew install git

Second, go git official website Download files and install manually.

mage-20180316120201

Test whether git is installed successfully

$ git --version
git version 2.16.2

Version Library

Create version Library

Create an empty directory first:

$ mkdir gitest
$ cd gitest/
$ pwd
/Users/junxi/gitest

Turn this directory into a manageable warehouse through git init command:

$ git init
Initialized empty Git repository in /Users/junxi/gitest/.git/

Add file to version Library

Write a readme MD file, as follows:

Git is a version control system.
Git is free software.

The file must be placed in the gitest directory (or its subdirectory), because this is a Git warehouse. This file can be found in the corresponding directory of the warehouse.

Putting a file into the git repository takes only two steps.

In the first step, use the command git add to add the file to the warehouse:

Usage: git add file_name1 file_name2 …

git add readme.md 

Before performing the second step, you can use the command git status to view the status:

$ git status -s
A  readme.md
$ git status 
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

    new file:   readme.md

Step 2: use the command git commit to tell Git to submit the file to the warehouse:

git commit -m "new creating a readme file"

Time travel

We successfully added and submitted a readme MD file. Now try to modify the contents of the file:

Git is a distributed version control system.
Git is free software.

Now run the git status command to see the results:

$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   readme.md

no changes added to commit (use "git add" and/or "git commit -a")

The git status command allows us to keep abreast of the current state of the warehouse. The above command tells us that readme MD has been modified, but no changes are ready to be submitted.

Although Git told us readme MD has been modified, but we want to see what has been modified. At this time, you need to use the git diff command to view:

$ git diff readme.md 
diff --git a/readme.md b/readme.md
index 46d49bf..9247db6 100644
--- a/readme.md
+++ b/readme.md
@@ -1,2 +1,2 @@
-Git is a version control system.
+Git is a distributed version control system.
 Git is free software.

git diff is to check the differences. Through this command, we can clearly see what has been modified. The display format is the general diff format of Unix.

Submit readme for the second time MD file:

$ git add readme.md 

$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   readme.md

$ git commit -m "add distributed"
[master b99e891] add distributed
 1 file changed, 1 insertion(+), 1 deletion(-)
 
$ git status
On branch master
nothing to commit, working tree clean

Version fallback

Modify readme again MD file, as follows:

Git is a distributed version control system.
Git is free software distributed under the GPL.

Then try to submit:

$ git add readme.md 
$ git commit -m "append GPL"
[master 49d0f9b] append GPL
 1 file changed, 1 insertion(+), 1 deletion(-) 

Like this, you constantly modify the file, and then constantly submit the modification to the version library. It's like when playing RPG game, you will automatically save the game status every time you pass a level. If a level hasn't passed, you can also choose to read the status of the previous level. Sometimes, you will save the disk manually before playing Boss, so that if you fail to play Boss, you can start from the nearest place. Git is the same. Whenever you think the file has been modified to a certain extent, you can "save a snapshot". This snapshot is called commit in GIT. Once you mess up the files or delete them by mistake, you can recover from the latest commit and continue to work instead of losing all the work results of several months.

Now let's review readme Several versions of the MD file have been submitted to the Git Repository:

Version 1: new creating a readme file

Git is a version control system.
Git is free software.

Version 2: add distributed

Git is a distributed version control system.
Git is free software.

Version 3: append GPL

Git is a distributed version control system.
Git is free software distributed under the GPL.

Of course, in actual work, how can we remember what is changed every time in a file with thousands of lines? Otherwise, what do we need the version control system to do. There must be a command in the version control system that can tell us the history. In Git, we use the git log command to check:

$ git log
commit 49d0f9b9bcf30069a3b0ed91ecf5397738a940e6 (HEAD -> master)
Author: junxi <xinlei3166@126.com>
Date:   Fri Mar 16 15:12:38 2018 +0800

    append GPL

commit b99e891f22fcf8cfcdd3aef737a6b7681b100976
Author: junxi <xinlei3166@126.com>
Date:   Fri Mar 16 14:43:09 2018 +0800

    add distributed

commit f2bc5b8abee58de182cce051b3e0e6d1c7431a22
Author: junxi <xinlei3166@126.com>
Date:   Fri Mar 16 14:04:37 2018 +0800

    new creating a readme file

The git log command displays the latest to farthest submission logs. We can see three submissions. The latest one is append GPL, the last one is add distributed, and the earliest one is new creating a readme file.

If you feel dazzled by too much output information, you can try adding -- pretty=oneline parameter:

$ git log --pretty=oneline
49d0f9b9bcf30069a3b0ed91ecf5397738a940e6 (HEAD -> master) append GPL
b99e891f22fcf8cfcdd3aef737a6b7681b100976 add distributed
f2bc5b8abee58de182cce051b3e0e6d1c7431a22 new creating a readme file

Now let's start the time shuttle and prepare readme How can MD go back to the previous version, that is, the version of "add distributed"?

First of all, Git must know which version the current version is. In Git, HEAD is used to represent the current version, that is, the latest submission 49d0f9b9bcf30069a3b0ed91ecf5397738a940e6 (note that my submission ID is certainly different from yours). The previous version is HEAD ^, and the previous version is HEAD ^. Of course, it's easier to write 100 versions up to 100, So it's written as HEAD~100.

Now, if we want to return the current version of "append GPL" to the previous version of "add distributed", we can use the git reset command:

$ git reset --hard HEAD^
HEAD is now at b99e891 add distributed

Look at readme Is the content of MD version add distributed

junxi-MacBook:gitest junxi$ cat readme.md 
Git is a distributed version control system.
Git is free software.

Sure enough.

You can also continue to go back to the previous version write a readme file, but wait a minute. However, let's use git log to see the status of the current version Library:

$ git log
commit b99e891f22fcf8cfcdd3aef737a6b7681b100976 (HEAD -> master)
Author: junxi <xinlei3166@126.com>
Date:   Fri Mar 16 14:43:09 2018 +0800

    add distributed

commit f2bc5b8abee58de182cce051b3e0e6d1c7431a22
Author: junxi <xinlei3166@126.com>
Date:   Fri Mar 16 14:04:37 2018 +0800

    new creating a readme file

The latest version of append GPL can no longer be seen! For example, you've been on the time shuttle from the 21st century to the 19th century. If you want to go back, you can't go back. What should you do?

In fact, there are still some methods. As long as the command line window above has not been closed, you can look up and find that the commit id of the append GPL is 49d0f9, Then you can specify to return to a future version:

$ git reset --hard 49d0f9
HEAD is now at 49d0f9b append GPL

There is no need to write the version number completely. The first few digits are OK. Git will automatically find it. Of course, you can't just write the first two digits, because git may find multiple version numbers and can't determine which one.

Take a closer look at readme Contents of MD:

$ cat readme.md 
Git is a distributed version control system.
Git is free software distributed under the GPL.

Sure enough, back to the latest.

Git version fallback is very fast, because git has an internal HEAD pointer to the current version. When you fallback the version, GIT only points the HEAD from to the append GPL:

mage-20180316161231

Change to point to add distributed:

mage-20180316161249

Then update the files in the workspace by the way. So you can locate the current version according to the version number you want the HEAD to point to.

Now, you go back to a certain version, turn off the computer, and regret the next morning. What if you want to restore to a new version? What if the new version of commit id cannot be found?

In git, there is always regret medicine to take. When you use $git reset --hard HEAD ^ to go back to the add distributed version, if you want to restore to the append GPL, you must find the commit id of the append GPL. Git provides a command git reflog to record your every command:

$ git reflog
49d0f9b (HEAD -> master) HEAD@{0}: reset: moving to 49d0f9
b99e891 HEAD@{1}: reset: moving to HEAD^
49d0f9b (HEAD -> master) HEAD@{2}: reset: moving to 49d0f9
b99e891 HEAD@{3}: reset: moving to HEAD^
49d0f9b (HEAD -> master) HEAD@{4}: reset: moving to 49d0f9
b99e891 HEAD@{5}: reset: moving to HEAD^
49d0f9b (HEAD -> master) HEAD@{6}: commit: append GPL
b99e891 HEAD@{7}: commit: add distributed
f2bc5b8 HEAD@{8}: commit (initial): new creating a readme file

Summary:

  • The version that HEAD points to is the current version. Therefore, Git allows us to shuttle through the history of versions and use the command git reset --hard commit_id.
  • Before the shuttle, you can check the submission history with git log to determine which version to fallback to.
  • To go back to the future, use git reflog to view the command history to determine which version to go back to in the future.

Workspace and staging area

One difference between Git and other version control systems such as SVN is the concept of staging area.

Working Directory

It is the directory you can see on the computer. For example, my gitest folder is a workspace:

mage-20180319100915

Repository

The workspace has a hidden directory Git, this is not a workspace, but a git version library.

There are many things stored in Git's version library, the most important of which is the temporary storage area called stage (or index), the first branch master automatically created by git for us, and a pointer to the master called HEAD.

git workspace version Library

We will talk about the concepts of branch and HEAD later.

As mentioned earlier, when we add files to Git version library, it is implemented in two steps:

The first step is to add the GIT file to the temporary storage area;

The second step is to submit the changes with git commit, which is actually to submit all the contents of the staging area to the current branch.

When we create Git version library, Git automatically creates the only master branch for us, so now, git commit is to submit changes to the master branch.

You can simply understand that all the file modifications that need to be submitted are put into the temporary storage area, and then all the modifications in the temporary storage area are submitted at one time.

As the saying goes, practice produces true knowledge. Now, let's practice it again, first on readme Modify MD, such as adding a line:

Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage.

Then, add a LICENSE text file in the workspace (write the content casually).

First check the status with git status:

$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   readme.md

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    LICENSE

no changes added to commit (use "git add" and/or "git commit -a")

Git tells us very clearly that readme MD has been modified, and LICENSE has never been added, so its status is Untracked.

Now, use the command git add twice to put readme After adding MD and LICENSE, use git status to check again:

$ git add readme.md LICENSE 
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   LICENSE
    modified:   readme.md

Now, the status of the staging area changes to this:

-

Therefore, the git add command is actually to put all the modifications to be submitted into the staging area (Stage), and then execute git commit to submit all the modifications in the staging area to the branch at one time.

$ git commit -m "understand how stage works"
[master 81673ab] understand how stage works
 2 files changed, 2 insertions(+)
 create mode 100644 LICENSE

Once submitted, if you haven't made any changes to the workspace, the workspace is "clean":

$ git status
On branch master
nothing to commit, working tree clean

Now the version library becomes like this, and there is no content in the staging area:

-

Summary:

Staging area is a very important concept of Git. If you understand the staging area, you will understand what many operations of Git do.

For children's shoes that don't understand what's going on in the temporary storage area, please scroll up the page and have a look again.

Management modification

Now, suppose you have fully mastered the concept of staging area. Next, we want to discuss why Git is better designed than other version control systems, because git tracks and manages changes, not files.

You ask, what is modification? For example, if you add a new line, it is a modification. If you delete a line, it is also a modification. If you change some characters, it is also a modification. If you delete some and add some, it is also a modification. Even if you create a new file, it is also a modification.

Why does Git manage modifications, not files? Let's do the experiment. The first step is to readme MD make a modification, such as adding a line:

$ cat readme.md 
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage.
Git tracks changes.

Then add:

$ git add readme.md 
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   readme.md

Then, modify readme md:

$ cat readme.md 
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage.
Git tracks changes of files.

Submission:

$ git commit -m "git tracks changes"
[master fd42bc4] git tracks changes
 1 file changed, 1 insertion(+)

After submitting, check the status:

$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   readme.md

no changes added to commit (use "git add" and/or "git commit -a")

Eh, why didn't the second modification be submitted?

Take it easy. Let's review the operation process:

First modification - > git add - > second modification - > git commit

You see, as we mentioned earlier, Git manages modifications. When you use the git add command, the first modification in the workspace is put into the staging area and ready to be submitted. However, the second modification in the workspace is not put into the staging area. Therefore, git commit is only responsible for submitting the modifications in the staging area, that is, the first modification is submitted, The second modification will not be submitted.

After submitting, use git diff head -- readme The MD command can view the difference between the latest version in the workspace and the version Library:

$ git diff HEAD -- readme.md 
diff --git a/readme.md b/readme.md
index 76d770f..a9c5755 100644
--- a/readme.md
+++ b/readme.md
@@ -1,4 +1,4 @@
 Git is a distributed version control system.
 Git is free software distributed under the GPL.
 Git has a mutable index called stage.
-Git tracks changes.
+Git tracks changes of files.

It can be seen that the second modification has not been submitted.

Then how to submit the second modification? You can continue git add and then git commit, or don't worry about submitting the first modification. First git add and then git commit, which is equivalent to submitting the two modifications together:

First modification - > git add - > second modification - > git add - > git commit

OK, now, submit the second modification, and then start the summary.

Summary:

Now, you understand how Git tracks changes. If you don't add the changes to the temporary storage area, it won't be added to the commit.

Undo modification

Naturally, you can't make mistakes. But it's two o'clock in the morning. You're catching up with a work report. You're reading me MD added a line:

$ cat readme.md 
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage.
Git tracks changes of files.
My stupid boss still prefers SVN.

Before you are ready to submit, a cup of coffee works. You suddenly find that "stupid boss" may cost you this month's bonus!

Since the mistake is discovered in time, it can be easily corrected. You can delete the last line and manually restore the file to the previous version. If you use git status to check:

$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   readme.md

no changes added to commit (use "git add" and/or "git commit -a")

You can find that Git will tell you that git checkout -- file can discard changes in the workspace:

$ git checkout -- readme.md

Gitme -- check out command MD means to put readme All modifications of MD files in the workspace are cancelled. There are two situations:

One is readme As like as two peas, MD has not been put in the temporary storage area since it has been modified.

One is readme MD has been added to the staging area and modified. Now, undo the modification and return to the state after adding to the staging area.

In short, it is to return the file to the state of the last git commit or git add.

Now, look at readme MD file content:

$ cat readme.md 
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage.
Git tracks changes.

The contents of the file were restored.

git checkout -- one of the file commands -- is very important. Without --, it becomes the command of "switching to another branch". We will encounter the git checkout command again in the later branch management.

Now suppose it's 3 a.m., you not only write some nonsense, but also git add to the temporary storage area:

$ cat readme.md 
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage.
Git tracks changes of files.
My stupid boss still prefers SVN.
$ git add readme.md 

Fortunately, you found this problem before commit. Check with git status. The modification has only been added to the temporary storage area and has not been submitted yet:

$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   readme.md

Git also tells us that the command git reset HEAD file can undo the modification of the temporary storage area and put it back into the work area:

$ git reset HEAD readme.md 
Unstaged changes after reset:
M   readme.md

The git reset command can either roll back the version or the modification of the staging area to the workspace. When we use HEAD, it means the latest version.

Check git status again. Now the staging area is clean and the workspace has been modified:

$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   readme.md

no changes added to commit (use "git add" and/or "git commit -a")

Remember how to discard workspace changes?

$ git checkout -- readme.md
$ git status
On branch master
nothing to commit, working tree clean
$ cat readme.md 
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage.
Git tracks change

ok.

Now, suppose you not only correct something wrong, but also submit it from the temporary storage area to the version library. What should you do? Remember Version fallback A section? You can go back to the previous version. However, this is conditional, that is, you haven't pushed your local version library to the remote. Remember Git is a distributed version control system? We will talk about the remote version library later. Once you push the "stupid boss" submission to the remote version library, you will be really miserable

Summary

Scenario 1: when you change the contents of a file in the workspace and want to discard the changes in the workspace directly, use the command git checkout -- file.

Scenario 2: when you not only mess up the contents of a file in the workspace, but also add it to the temporary storage area, you want to discard the modification in two steps. The first step is to use the command git reset HEAD file to return to scenario 1. The second step is to operate according to scenario 1.

Scenario 3: if you want to cancel this submission when you have submitted inappropriate modifications to the version library, please refer to Version fallback Section, but only if it is not pushed to the remote library.

Delete file

In Git, deleting is also a modification operation. Let's add a new file test Txt to Git and submit:

$ cat test.txt 
new createing a test.txt file.

$ git add test.txt 
$ git commit -m "add test.txt"
[master 6aade49] add test.txt
 1 file changed, 2 insertions(+)
 create mode 100644 test.txt

In general, you usually delete useless files directly in the file manager, or delete them with rm command:

$ rm test.txt 

At this time, Git knows that you have deleted files, so the workspace and version library are inconsistent. The git status command will immediately tell you which files have been deleted:

$ git status
On branch master
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    deleted:    test.txt

no changes added to commit (use "git add" and/or "git commit -a")

Now you have two choices. First, if you really want to delete the file from the version library, use the command git rm to delete it, and git commit:

$ git rm test.txt
rm 'test.txt'
$ git commit -m "remove test.txt"
[master 3f1febc] remove test.txt
 1 file changed, 2 deletions(-)
 delete mode 100644 test.txt

The file is now deleted from the repository.

Another case is that the deleted file is wrong. Because there are still files in the version library, it is easy to restore the wrongly deleted file to the latest version:

$ git checkout -- test.txt

git checkout actually replaces the version of the workspace with the version in the version library. No matter whether the workspace is modified or deleted, it can be "restored with one click".

Summary

The command git rm is used to delete a file. If a file has been submitted to the version library, you never have to worry about accidental deletion, but be careful. You can only restore the file to the latest version, and you will lose the content you modified after the last submission.

Remote warehouse

So far, we have mastered how to time travel a file in Git warehouse. You don't have to worry about file backup or loss anymore.

However, children's shoes who have used the centralized version control system SVN will stand up and say that these functions have long been available in SVN. I don't see anything special about Git.

Yes, if you only manage file history in one warehouse, Git is no different from SVN. In order to ensure that what you have learned about Git is worth more and you will never regret it in the future, this chapter begins to introduce one of GIT's killer functions (note one, that is, there are two, three...): remote warehouse.

Git is a distributed version control system. The same git warehouse can be distributed to different machines. How is it distributed? At first, there must be only one machine with an original version library. Later, other machines can "clone" this original version library, and the version Library of each machine is actually the same, there is no primary or secondary.

You must think that you need at least two machines to play remote library, don't you? But I only have one computer. How do I play?

In fact, multiple version libraries can be cloned on one computer, as long as they are not in the same directory. However, in real life, no one will be so stupid to play with several remote libraries on one computer, because it is meaningless to play with several remote libraries on one computer, and the hanging of the hard disk will cause all libraries to hang up, so I won't tell you how to clone multiple warehouses on one computer.

The actual situation is often like this. Find a computer to act as a server and start it 24 hours a day. Everyone else will clone a copy from this "server" warehouse to their own computer, push their submissions to the server warehouse, and also pull others' submissions from the server warehouse.

You can build a server running git by yourself, but at this stage, building a server to learn Git is definitely a fuss. Fortunately, there is a man called GitHub From the name, we can see that this website provides Git warehouse hosting service. Therefore, as long as you register a GitHub account, you can get Git remote warehouse for free.

Please register your GitHub account before continuing to read the following content. Since the transmission between your local Git warehouse and GitHub warehouse is encrypted through SSH, you need to set:

Step 1: create SSH Key. In the user's home directory, see if there is any ssh directory. If yes, check whether there is ID in this directory_ RSA and id_rsa. If you already have these two files, you can skip to the next step directly. If not, open Shell (open Git Bash under Windows) and create SSH Key:

$ ssh-keygen -t rsa -C "xxx@126.com"
$ ll ~/.ssh/
total 56
-rw-------  1 junxi  staff  1679 12 11 09:51 id_rsa
-rw-r--r--  1 junxi  staff   396 12 11 09:51 id_rsa.pub

If all goes well, you can find it in the user's home directory ssh directory with id_rsa and id_rsa.pub two files, which are the secret key pair and ID of SSH Key_ RSA is the private key and cannot be disclosed. id_rsa.pub is a public key that can be confidently told to anyone.

Step 2: log in to GitHub and open the "Account settings" and "SSH Keys" pages:

Then, click "Add SSH Key", fill in any Title, and paste ID in the Key text box_ rsa. Contents of pub file:

mage-20180319113227

Click "Add Key" and you should see the added Key:

mage-20180319113324

Why does GitHub need SSH Key? Because GitHub needs to recognize that the submission you push is really pushed by you, not pretended by others, and Git supports SSH protocol, GitHub can confirm that only you can push as long as you know your public key.

Of course, GitHub allows you to add multiple keys. Suppose you have several computers. You submit them at the company and at home. As long as you add the Key of each computer to GitHub, you can push them to GitHub on each computer.

Finally, a friendly tip: anyone can see the Git warehouse hosted free of charge on GitHub (but only you can change it yourself). So don't put sensitive information in it.

If you don't want others to see the Git library, there are two ways. One is to pay the intersection protection fee to let GitHub turn the public warehouse into private, so that others can't see it (unreadable and unwritten). Another way is to build a Git server by yourself. Because it's your own Git server, others can't see it. This method, which we will talk about later, is quite simple and necessary for internal development of the company.

After making sure you have a GitHub account, we will start learning about remote warehouse.

Summary

"With the remote warehouse, mom doesn't have to worry about my hard disk anymore."—— Git point reader

Add remote library

The current scenario is that after you have created a Git warehouse locally, you want to create a Git warehouse in GitHub and synchronize the two warehouses remotely. In this way, the warehouse on GitHub can be used as a backup and other people can cooperate through the warehouse. It is really killing multiple birds with one stone.

First, log in to GitHub, and then find the "Create a new repo" button in the upper right corner to create a new warehouse:

mage-20180319113715

Fill in gitest in the Repository name and keep the default settings. Click the "Create repository" button to successfully create a new Git Repository:

mage-20180319113746

At present, the gitest warehouse on GitHub is still empty. GitHub tells us that we can clone a new warehouse from this warehouse, or associate an existing local warehouse with it, and then push the contents of the local warehouse to GitHub warehouse.

Now, according to the prompt of GitHub, run the command under the local gitest warehouse:

$ pwd
/Users/junxi/gitest
$ git remote add origin git@github.com:junxi3166/gitest.git

Please be sure to replace the above junxi3166 with your own GitHub account name. Otherwise, you are locally associated with my remote library. There is no problem with the association, but you can't push it in the future because your SSH Key public key is not in my account list.

After adding, the name of the remote library is origin, which is the default name of Git. It can also be changed to other names, but the name origin can be known as the remote library at a glance.

Next, you can push all the contents of the local library to the remote library:

$ git push -u origin master
Counting objects: 20, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (15/15), done.
Writing objects: 100% (20/20), 1.63 KiB | 837.00 KiB/s, done.
Total 20 (delta 5), reused 0 (delta 0)
remote: Resolving deltas: 100% (5/5), done.

To github.com:junxi3166/gitest.git
 * [new branch]      master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.

Push the contents of the local library to the remote. Using the git push command is actually pushing the current branch master to the remote.

Since the remote library is empty, when we push the master branch for the first time, we add the - u parameter. Git will not only push the contents of the local master branch to the new remote master branch, but also associate the local master branch with the remote master branch. In the future, we can simplify the command when pushing or pulling.

After successful push, as like as two peas in the GitHub page, you can see that the contents of the remote library are exactly the same as those of the local library.

mage-20180319142156

From now on, as long as the submission is made locally, you can use the command:

$ git push origin master

Push the latest changes of the local master branch to GitHub, and now you have a real distributed version library!

SSH warning

When you first use Git's clone or push command to connect to GitHub, you will get a warning:

The authenticity of host 'github.com (13.250.177.223)' can't be established.
RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8.
Are you sure you want to continue connecting (yes/no)?

This is because Git uses SSH connection. When verifying the Key of GitHub server for the first time, you need to confirm whether the fingerprint information of GitHub Key really comes from GitHub server, and enter yes.

Git will output a warning that you have added GitHub's Key to a local trust list:

Warning: Permanently added 'github.com,13.250.177.223' (RSA) to the list of known hosts.

This warning will only appear once, and there will be no warning for subsequent operations.

If you are really worried about someone posing as a GitHub server, you can check it before entering yes Fingerprint information of RSA Key of GitHub Whether it is consistent with that given by SSH connection.

Summary

To associate a remote library, use the command git remote add origin git@server-name:path/repo-name.git;

After association, use the command git push -u origin master to push all the contents of the master branch for the first time;

Thereafter, after each local submission, you can use the command git push origin master to push the latest modification as long as necessary;

One of the biggest benefits of the distributed version system is that working locally does not need to consider the existence of remote libraries, that is, it can work normally with or without networking, while SVN refuses to work when there is no networking! When there is a network, it is very convenient to push the local submission to complete the synchronization!

Clone from remote library

Last time we talked about how to associate remote libraries when there are local libraries first and then remote libraries.

Now, assuming we develop from scratch, the best way is to create a remote library first, and then clone it from the remote library.

First, log in to GitHub and create a new warehouse called gitskills:

mage-20180319142804

We check Initialize this repository with a README, so GitHub will automatically create a readme for us MD file. After creation, you can see readme MD file:

mage-20180319142831

Now that the remote library is ready, the next step is to clone a local library with the command git clone:

$ git clone git@github.com:junxi3166/gitskills.git
Cloning into 'gitskills'...
Warning: Permanently added the RSA host key for IP address '13.229.188.59' to the list of known hosts.
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (3/3), done.
$ cd gitskills/
$ ls
README.md

Change the address of Git library to your own, and then enter gitskills directory to see that readme is available MD file.

If there are multiple people working together to develop, then each person can clone one from a remote location.

You may also notice that GitHub gives more than one address, which can also be used https://github.com/junxi3166/gitskills.git Such an address. In fact, git supports a variety of protocols. The default git: / / uses ssh, but other protocols such as HTTPS can also be used.

In addition to the slow speed of using https, the biggest trouble is that you must enter a password for each push. However, in some companies that only open the http port, you can't use the ssh protocol but only https.

Summary

To clone a warehouse, you must first know the address of the warehouse, and then clone it with the git clone command.

Git supports a variety of protocols, including https, but the native git protocol supported by ssh is the fastest.

Branch Management

The branch is the parallel universe in science fiction movies. When you are trying to learn Git in front of the computer, another you are trying to learn SVN in another parallel universe.

If two parallel universes don't interfere with each other, it won't affect you now. However, at a certain point in time, two parallel universes merge. As a result, you learn both Git and SVN!

0

What is the use of branching in practice? Suppose you are going to develop a new function, but it takes two weeks to complete it. In the first week, you wrote 50% of the code. If you submit it immediately, because the code has not been written, the incomplete code base will make others unable to work. If the code is written and submitted again, there is a huge risk of losing the daily progress.

Now that you have branches, you don't have to be afraid. You create a branch that belongs to you, but others can't see it and continue to work normally on the original branch. You work on your own branch and submit it if you want. After the development is completed, you can merge it into the original branch at one time. In this way, it is safe and does not affect the work of others.

Other version control systems, such as SVN, have branch management, but after using it, you will find that these version control systems create and switch branches more slowly than snails, which is unbearable. As a result, the branch function has become a decoration and everyone doesn't use it.

But Git's branches are different. Whether creating, switching or deleting branches, Git can complete them in 1 second! Whether your version library is 1 file or 10000 files.

Create and merge branches

stay Version fallback As you already know, Git strings them into a timeline for each submission, which is a branch. So far, there is only one timeline. In Git, this branch is called the main branch, that is, the master branch. Strictly speaking, HEAD does not point to submission, but to master, which points to submission. Therefore, HEAD points to the current branch.

At the beginning, the master branch is a line. Git uses master to point to the latest submission and HEAD to point to master to determine the current branch and the submission point of the current branch:

-

Each time you submit, the master branch will move forward one step. In this way, as you continue to submit, the line of the master branch will become longer and longer:

it-

When we create a new branch, such as dev, Git creates a new pointer called dev, which points to the same commit as the master, and then points the HEAD to dev, indicating that the current branch is on dev:

-

You see, Git creates a branch very quickly, because in addition to adding a dev pointer and changing the direction of HEAD, there is no change in the files in the workspace!

However, from now on, the modification and submission of the workspace are aimed at the dev branch. For example, after a new submission, the dev pointer moves forward one step, while the master pointer remains unchanged:

-

If our work on dev is completed, we can merge dev into the master. How does Git merge? The simplest way is to directly point the master to the current commit of dev to complete the merge:

-

So Git merges branches very quickly! Just change the pointer and the content of the workspace will remain the same!

After merging the branches, you can even delete the dev branch. Deleting the dev branch is to delete the dev pointer. After deletion, we have a master branch left:

-

It's amazing. Can you see that some submissions are done through branches?

it-

Let's start the actual combat.

First, we create the dev branch, and then switch to the dev branch:

$ pwd
/Users/junxi/gitskills
$ git checkout -b dev
Switched to a new branch 'dev'

The git checkout command plus the - b parameter indicates creation and switching, which is equivalent to the following two commands:

$ git branch dev
$ git checkout dev
Switched to branch 'dev'

Then, use the git branch command to view the current branch:

$ git branch
* dev
  master

The git branch command will list all branches, and the current branch will be preceded by a * sign.

Then, we can commit normally on the dev branch, such as readme Modify MD and add a line:

Creating a new branch is quick.

Then submit:

$ git add README.md 
$ git commit -m "branch test"
[dev be2e7c9] branch test
 1 file changed, 1 insertion(+)

Now that the dev branch is completed, we can switch back to the master branch:

$ git checkout master
Switched to branch 'master'

After switching back to the master branch, check readme MD file, the content just added is missing! Because the commit is on the dev branch, and the commit point of the master branch has not changed at the moment:

$ cat README.md 
# gitskills
gitskills

-

Now, let's merge the work of dev branch into master branch:

$ git merge dev
Updating 09f920d..be2e7c9
Fast-forward
 README.md | 1 +
 1 file changed, 1 insertion(+)

The git merge command is used to merge the specified branch to the current branch. After merging, view readme You can see that the content of MD is exactly the same as the latest submission of dev branch.

$ cat README.md 
# gitskills
gitskills
Creating a new branch is quick.

Noting the fast forward information above, Git told us that the merge is in the "fast forward mode", that is, direct the master to the current commit of dev, so the merge speed is very fast.

Of course, not every merge can be fast forward. We will talk about other merging methods later.

After merging, you can safely delete the dev branch:

$ git branch -d dev
Deleted branch dev (was be2e7c9).

After deleting the branch, you can only view the branch master:

$ git branch
* master

Because creating, merging and deleting branches are very fast, Git encourages you to use branches to complete a task and delete branches after merging. This has the same effect as working directly on the master branch, but the process is safer.

Summary

Git encourages extensive use of branches:

View branch: git branch

Create branch: git branch < name >

Switch branches: git checkout < name >

Create + switch branch: git checkout - B < name >

Merge a branch to the current branch: git merge < name >

Delete branch: git branch - d < name >

Conflict resolution

Nine times out of ten, merging branches is not always easy.

Prepare a new feature1 branch and continue our new branch development:

$ git checkout -b feature1
Switched to a new branch 'feature1'

Modify readme In the last line of MD, change to:

Creating a new branch is quick AND simple.

Submit on feature1 branch:

$ git add README.md 
$ git commit -m "AND simple"
[feature1 3a8b438] AND simple
 1 file changed, 1 insertion(+), 1 deletion(-)

Switch to the master branch:

$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 1 commit.
  (use "git push" to publish your local commits)

The remote gi master will automatically submit 1 branch ahead of the current one.

On the master branch, add readme The last line of the MD file should read:

Creating a new branch is quick & simple.

Submission:

$ git add README.md 
$ git commit -m "& simple"
[master 23307ae] & simple
 1 file changed, 1 insertion(+), 1 deletion(-)

Now, both the master branch and the feature1 branch have new submissions respectively, which becomes as follows:

-

In this case, Git cannot perform "quick merge" and can only try to merge their changes, but this kind of merge may have conflicts. Let's try:

$ git merge feature1
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.

Sure enough, there was a conflict! Git told us that readme The MD file has conflicts, which must be manually resolved before submission. git status can also tell us the conflicting files:

$ git status
On branch master
Your branch is ahead of 'origin/master' by 2 commits.
  (use "git push" to publish your local commits)

You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Unmerged paths:
  (use "git add <file>..." to mark resolution)

    both modified:   README.md

no changes added to commit (use "git add" and/or "git commit -a")

We can view readme directly Contents of MD:

$ cat README.md 
# gitskills
gitskills
<<<<<<< HEAD
Creating a new branch is quick & simple.
=======
Creating a new branch is quick AND simple.
>>>>>>> feature1

Git marks the contents of different branches with < < < < <, =========, > > > > > > >. We modify them as follows and save them:

Creating a new branch is quick and simple.

Resubmission:

$ git add README.md 
$ git commit -m "conflict fixed"
[master 5f3dff6] conflict fixed

Now, the master branch and feature1 branch become the following figure:

-

Using git log with parameters, you can also see the merging of branches:

$ git log --graph --pretty=oneline --abbrev-commit
*   5f3dff6 (HEAD -> master) conflict fixed
|\  
| * 3a8b438 (feature1) AND simple
* | 23307ae & simple
|/  
* be2e7c9 branch test
* 09f920d (origin/master, origin/HEAD) Initial commit

Finally, delete the feature1 branch:

$ git branch -d feature1
Deleted branch feature1 (was 3a8b438).

Done.

Summary

When Git cannot automatically merge branches, the conflict must be resolved first. After resolving the conflict, submit and merge.

Use the git log --graph command to see the branch merge diagram.

Branch management strategy

Usually, when merging branches, Git will use Fast forward mode if possible, but in this mode, branch information will be lost after deleting branches.

If the Fast forward mode is to be forcibly disabled, Git will generate a new commit when merging, so that the branch information can be seen from the branch history.

Let's practice -- git merge in no FF mode:

First, still create and switch the dev branch:

$ git checkout -b dev

Modify readme MD file and submit a new commit:

$ # vi README.md 
$ git add README.md
$ git commit -m "fenzhi."

Now, let's switch back to master:

$ git checkout master

When preparing to merge dev branches, please note the -- no FF parameter, which means that Fast forward is disabled:

$ git merge --no-ff -m "merge with no-ff" dev
Merge made by the 'recursive' strategy.
 README.md | 1 +
 1 file changed, 1 insertion(+)

Because a new commit will be created in this merge, add the - m parameter to write the commit description.

After merging, let's use git log to see the branch history:

$ git log --graph --pretty=oneline --abbrev-commit
*   535190d (HEAD -> master) merge with no-ff
|\  
| * c5e8566 (dev) fenzhi.
|/  
*   5f3dff6 conflict fixed
|\  
| * 3a8b438 AND simple
* | 23307ae & simple
|/  
* be2e7c9 branch test
* 09f920d (origin/master, origin/HEAD) Initial commit

It can be seen that without using the Fast forward mode, the merge is like this:

-1

Branching strategy

In actual development, we should carry out branch management according to several basic principles:

First, the master branch should be very stable, that is, it is only used to release new versions and cannot work on it at ordinary times;

Where do you work? Work on the dev branch, that is, the dev branch is unstable. At some time, for example, when version 1.0 is released, merge the dev branch into the master, and release version 1.0 in the master branch;

You and your friends, everyone works on the dev branch. Everyone has their own branch. Just merge on the dev branch from time to time.

So the branch of teamwork looks like this:

-1

Summary

Git branch is very powerful and should be fully applied in team development.

When merging branches, add the -- no FF parameter to merge in the normal mode. After merging, there are branches in the history. It can be seen that merging has been done, while fast forward merging can not see that merging has been done.

Bug branch

In software development, bugs are just as common. Bugs need to be repaired. In Git, because branches are so powerful, each bug can be repaired through a new temporary branch. After repair, merge the branches, and then delete the temporary branch.

When you receive a task to fix a bug code 101, naturally, you want to create a branch issue-101 to fix it, but wait, the current work on dev has not been submitted:

$ git status
# On branch dev
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       new file:   hello.py
#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   README.md

It's not that you don't want to submit, but that the work is only halfway through and can't be submitted. It's expected to take another day to complete. However, the bug must be fixed within two hours. What should I do?

Fortunately, Git also provides a stash function, which can "store" the current work site and continue to work after restoring the site in the future:

$ git stash
Saved working directory and index state WIP on dev: 6224937 add merge
HEAD is now at 6224937 add merge

Now, viewing the workspace with git status is clean (unless there are files that are not managed by Git), so you can safely create branches to fix bug s.

First, determine which branch you want to fix the bug on. If you need to fix it on the master branch, create a temporary branch from the master:

$ git checkout master
Already on 'master'
Your branch is ahead of 'origin/master' by 6 commits.
  (use "git push" to publish your local commits)
$ git checkout -b issue-101
Switched to a new branch 'issue-101'

To fix the bug, change "gitskills" to "gitskills", and then submit:

$ git add README.md 
$ git commit -m "fix bug 101"
[issue-101 966ad32] fix bug 101
 1 file changed, 1 insertion(+), 1 deletion(-)

After the repair, switch to the master branch, complete the merge, and finally delete the issue-101 branch:

$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 6 commits.
  (use "git push" to publish your local commits)
$ git merge --no-ff -m "merge bug fix 101" issue-101
Merge made by the 'recursive' strategy.
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
$ git branch -d issue-101
Deleted branch issue-101 (was 966ad32)

Great, the original two-hour bug fix took only five minutes! Now, it's time to go back to the dev branch!

$ git checkout dev
Switched to branch 'dev'
$ git status
# On branch dev
nothing to commit (working directory clean)

The work area is clean. Where was the work site just now? Use git stash list command to see:

$ git stash list
stash@{0}: WIP on dev: 6224937 add merge

The job site is still there. Git has stored the stash content somewhere, but it needs to be restored. There are two ways:

First, restore with git stash apply, but after restoration, the stash content will not be deleted. You need to use git stash drop to delete it;

Another way is to use git stash pop to delete the stash content while restoring:

$ git stash pop
# On branch dev
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       new file:   hello.py
#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   README.md
#
Dropped refs/stash@{0} (f624f8e5f082f2df2bed8a4e09c12fd2943bdd40)

Then use git stash list to view, and you can't see any stash content:

$ git stash list

You can stash multiple times. When restoring, first check with git stash list, and then restore the specified stash with the command:

$ git stash apply stash@{0}

Summary

When fixing a bug, we will create a new bug branch to fix it, then merge and delete it;

When the work at hand is not finished, first git stash the work site, then fix the bug, and then git stash pop to return to the work site.

Feature branch

In software development, there are always endless new functions to be added.

When adding a new function, you certainly don't want to mess up the main branch because of some experimental code. Therefore, every time you add a new function, you'd better create a new feature branch, develop it on it, merge it after completion, and finally delete the feature branch.

Now, you finally have a new task: developing a new feature code named Vulcan, which is planned for the next generation of starships.

So we are ready to develop:

$ git checkout -b feature-vulcan

After 5 minutes, the development is completed:

$ git add vulcan.py 
$ git status
On branch feature-vulcan
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   vulcan.py
    
$ git commit -m "add feature vulcan"
[feature-vulcan 0c7a1a3] add feature vulcan
 1 file changed, 1 insertion(+)
 create mode 100644 vulcan.py

Switch back to dev and prepare for merging:

$ git checkout dev

If everything goes well, the feature branch and bug branch are similar. Merge and delete them.

But,

At this time, after receiving the order from the superior, the new function must be cancelled due to insufficient funds!

Although it was done in vain, this branch must be destroyed on site:

$ git branch -d feature-vulcan
error: The branch 'feature-vulcan' is not fully merged.
If you are sure you want to delete it, run 'git branch -D feature-vulcan'.

Destroy failed. Git kindly reminds that the feature Vulcan branch has not been merged. If it is deleted, the modifications will be lost. If you want to forcibly delete it, you need to use the command git branch - D feature Vulcan.

Now let's forcibly delete:

$ git branch -D feature-vulcan
Deleted branch feature-vulcan (was 0c7a1a3).

Finally deleted successfully!

Summary

To develop a new feature, it is best to create a new branch;

If you want to discard a branch that has not been merged, you can forcibly delete it through git branch - d < name >.

Multi person collaboration

When you clone from a remote warehouse, in fact, Git automatically corresponds the local master branch to the remote master branch, and the default name of the remote warehouse is origin.

To view the information of the remote library, use git remote:

$ git remote
origin

Alternatively, use git remote -v to display more detailed information:

$ git remote -v
origin  git@github.com:junxi3166/gitskills.git (fetch)
origin  git@github.com:junxi3166/gitskills.git (push)

The address of the origin that can be crawled and pushed is shown above. If you don't have push permission, you can't see the push address.

Push branch

Push branch is to push all local submissions on the branch to the remote library. When pushing, specify the local branch, so Git will push the branch to the remote branch corresponding to the remote library:

$ git push origin master

If you want to push other branches, such as dev, change to:

$ git push origin dev

However, it is not necessary to push the local branches to the remote, so which branches need to be pushed and which do not?

  • The master branch is the main branch, so it should be synchronized with the remote branch at all times;
  • dev branch is a development branch. All members of the team need to work on it, so they also need to synchronize with remote;
  • The bug branch is only used to fix bugs locally, so there is no need to push it to the remote, unless the boss wants to see how many bugs you fix every week;
  • Whether the feature branch is pushed to the remote depends on whether you develop it with your small partners.

In short, in Git, branches can hide and play locally. Whether to push depends on your mood!

Grab branch

When multiple people collaborate, everyone will push their own modifications to the master and dev branches.

Now, simulate your little partner and clone it on another computer (note to add SSH Key to GitHub) or in another directory of the same computer:

$ git clone git@github.com:junxi3166/gitskills.git skills
Cloning into 'skills'...
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (3/3), done.
$ cd skills/
$ git remote -v
origin  git@github.com:junxi3166/gitskills.git (fetch)
origin  git@github.com:junxi3166/gitskills.git (push)

When your partner clone s from a remote database, by default, your partner can only see the local master branch. If you don't believe it, you can use the git branch command to see:

$ git branch
* master

Now, if your little partner wants to develop on the dev branch, he must create the dev branch of the remote origin to the local, so he uses this command to create the local dev branch:

$ git checkout -b dev

From time to time, he can modify dev to remote, and then continue to:

$ # vi hello.py
$ git add hello.py 
$ git commit -m "add two hello"
[dev 5bd8a63] add two hello
 1 file changed, 1 insertion(+)
 create mode 100644 hello.py
$ git push origin dev
Counting objects: 3, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 280 bytes | 280.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To github.com:junxi3166/gitskills.git
 * [new branch]      dev -> dev

Your little partner has pushed his submission to the origin/dev branch, and it happens that you have also modified the same file and tried to push:

$ # vi hello.py
$ git add hello.py 
$ git commit -m "add coding: _*_ utf-8 _*_"
[dev 003e6ed] add coding: _*_ utf-8 _*_
 1 file changed, 1 insertion(+)
 create mode 100644 hello.py
$ git push origin dev
To github.com:junxi3166/gitskills.git
 ! [rejected]        dev -> dev (fetch first)
error: failed to push some refs to 'git@github.com:junxi3166/gitskills.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

The push failed because there is a conflict between your partner's latest submission and the submission you are trying to push. The solution is also very simple. Git has prompted us to grab the latest Submission from origin/dev with git pull, then merge locally, solve the conflict, and then push:

$ git pull
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 3 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
From github.com:junxi3166/gitskills
 * [new branch]      ddd        -> origin/ddd
 * [new branch]      dev        -> origin/dev
There is no tracking information for the current branch.
Please specify which branch you want to merge with.
See git-pull(1) for details.

    git pull <remote> <branch>

If you wish to set tracking information for this branch you can do so with:

    git branch --set-upstream-to=origin/<branch> dev

git pull also failed because the link between the local dev branch and the remote origin/dev branch is not specified. According to the prompt, set the link between Dev and origin/dev:

$ git branch --set-upstream-to=origin/dev dev
Branch 'dev' set up to track remote branch 'dev' from 'origin'.

Then pull:

$ git pull
Auto-merging hello.py
CONFLICT (add/add): Merge conflict in hello.py
Automatic merge failed; fix conflicts and then commit the result.

git pull is successful this time, but there are conflicts in the merge, which need to be solved manually. The solution is the same as that in branch management Conflict resolution Exactly the same. After solving the problem, submit and then push:

$ # vi hello.py 
$ git add hello.py 
$ git commit -m "merge & fix hello.py"
[dev ac35808] merge & fix hello.py
$ git push origin dev
Counting objects: 21, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (14/14), done.
Writing objects: 100% (21/21), 1.75 KiB | 1.75 MiB/s, done.
Total 21 (delta 3), reused 0 (delta 0)
remote: Resolving deltas: 100% (3/3), done.
To github.com:junxi3166/gitskills.git
   5bd8a63..ac35808  dev -> dev

Therefore, the working mode of multi person cooperation is usually as follows:

  1. First, you can try to push your own modifications with git push origin branch name;
  2. If the push fails, you need to use git pull to try to merge because the remote branch is newer than your local branch;
  3. If there is a conflict in the merger, resolve the conflict and submit it locally;
  4. If there is no conflict or the conflict is solved, then push it with git push origin branch name to succeed!

If git pull prompts "no tracking information", it indicates that the link relationship between the local branch and the remote branch has not been created. Use the command git branch -- set upstream branch name origin / branch name.

This is the working mode of multi person cooperation. Once you are familiar with it, it is very simple.

Summary

  • To view the remote library information, use git remote -v;
  • If the newly created local branch is not pushed to the remote, it will not be visible to others;
  • Push the branch locally, and use git push origin branch name. If the push fails, first grab the remote new submission with git pull;
  • Create a branch corresponding to the remote branch locally. Use git checkout - B branch name origin / branch name. The names of the local and remote branches should be the same;
  • Establish the association between local branch and remote branch, and use git branch -- set upstream branch name origin / branch name;
  • Grab the branch from the remote and use git pull. If there is a conflict, deal with the conflict first.

Label management

When publishing a version, we usually tag it in the version library first, so that we can only determine the version at the time of labeling. Whenever we take the version of a label in the future, we will take out the historical version of the labeled time. Therefore, the tag is also a snapshot of the version library.

Although Git's label is a snapshot of the version library, it is actually a pointer to a commit (much like a branch, right? But the branch can move, but the label cannot move). Therefore, the creation and deletion of labels are completed in an instant.

Git has commit. Why introduce tag?

"Please package and release the version from last Monday. The commit number is 6a5819e..."

"It's hard to find a bunch of messy numbers!"

If you choose another way:

"Please package and release the version from last Monday. The version number is v1.2"

"OK, just find the commit according to tag v1.2!"

Therefore, tag is a meaningful name that people can easily remember. It is tied to a commit.

create label

Tagging in Git is very simple. First, switch to the branch that needs tagging:

$ git branch
* dev
  master
$ git checkout master
Switched to branch 'master'

Then, click the command git tag < name > to type a new tag:

$ git tag v1.0

You can view all tags with the command git tag:

$ git tag
v1.0

The default tag is printed on the newly submitted commit. Sometimes, if you forget to label, for example, it's Friday, but the label should be marked on Monday, what should you do?

The method is to find the commit id of the historical submission and then mark it:

$ git log --pretty=oneline --abbrev-commit
4fef11f (HEAD -> master, tag: v1.0) merge bug fix 101
966ad32 fix bug 101
535190d merge with no-ff
c5e8566 fenzhi.
5f3dff6 conflict fixed
23307ae & simple
3a8b438 AND simple
be2e7c9 branch test
09f920d (origin/master, origin/ddd, origin/HEAD) Initial commit

For example, to fenzhi This submission is labeled. Its corresponding commit id is c5e8566. Type in the command:

$ git tag v0.9 c5e8566

Then use the command git tag to view the label:

$ git tag
v0.9
v1.0

Note that the labels are not listed in chronological order, but in alphabetical order. You can use git show < tagName > to view tag information:

$ git show v0.9
commit c5e8566a61a1c889dc3a56f685eaf97dc9b1c2fe (tag: v0.9)
Author: junxi <xinlei3166@126.com>
Date:   Mon Mar 19 15:42:34 2018 +0800

    fenzhi.

diff --git a/README.md b/README.md
index 6e05639..b565a7f 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,4 @@
 # gitskills
 gitskills
 Creating a new branch is quick and simple.
+fenzhi.

As you can see, v0 9 really hit fenzhi This submission.

You can also create a label with a description, specify the label name with - A and specify the description text with - m:

$ git tag -a v0.1 -m "version 0.1" 09f920d

Use the command git show < tagName > to see the description text:

$ git show v0.1
tag v0.1
Tagger: junxi <xinlei3166@126.com>
Date:   Tue Mar 20 10:19:47 2018 +0800

version 0.1

commit 09f920d5df09b29d762ab839b516dde1339c36e0 (tag: v0.1, origin/master, origin/ddd, origin/HEAD)
Author: junxi <xinlei3166@126.com>
Date:   Mon Mar 19 14:28:02 2018 +0800

    Initial commit

diff --git a/README.md b/README.md
new file mode 100644
index 0000000..7f15fca
--- /dev/null
+++ b/README.md
@@ -0,0 +1,2 @@
+# gitskills
+gitskills

You can also sign a label with the private key through - s:

$ git tag -s v0.2 -m "version 0.2" be2e7c9

The signature adopts PGP signature. Therefore, gpg (GnuPG) must be installed first. If gpg is not found or there is no gpg key pair, an error will be reported:

fatal: cannot run gpg: No such file or directory
error: gpg failed to sign the data
error: unable to sign the tag

If an error is reported, please refer to GnuPG Help documentation Configure Key.

$ brew install gnupg
$ gpg --gen-key
$ gpg --list-keys
$ gpg --list-secret-keys
$ git config --global user.signingkey <GPG-key-id>

Use the command git show < tagName > to see the PGP signature information:

$ git show v0.2

Summary

  • The command git tag < name > is used to create a new tag. The default is HEAD. You can also specify a commit id;
  • git tag -a <tagname> -m "blablabla..." Label information can be specified;
  • git tag -s <tagname> -m "blablabla..." PGP signature label can be used;
  • The command git tag allows you to view all tags.

Operation label

If the label is wrong, it can also be deleted:

$ git tag -d v0.1

Because the created tags are only stored locally and will not be automatically pushed to the remote. Therefore, the wrong label can be safely deleted locally.

If you want to push a tag to the remote, use the command git push origin < tagName >:

$ git push origin v1.0

Or, push all local tags that have not been pushed to the remote at one time:

$ git push origin --tags

If the tag has been pushed to a remote location, it's a little troublesome to delete the remote tag. First delete it locally:

$ git tag -d v0.9

Then, delete from remote. The delete command is also push, but the format is as follows:

$ git push origin :refs/tags/v0.9

To see if the tag is really deleted from the remote library, you can log in to GitHub.

Summary

  • The command git push origin < tagName > can push a local label;
  • The command git push origin --tags can push all local tags that have not been pushed;
  • The command git tag - d < tagName > can delete a local tag;
  • The command git push origin: refs / tags / < tagName > can delete a remote tag.

Custom Git

stay Install Git In the section, we have configured user Name and user Email, in fact, Git has many configurable items.

For example, making Git display color will make the command output look more eye-catching:

mage-20180320112612

Git ignore files

Sometimes, you have to put some files in Git working directory, but you can't submit them, such as the configuration file that saves the database password. Each time git status displays Untracked files, Children's shoes with obsessive-compulsive disorder must be unhappy.

Fortunately, Git takes into account everyone's feelings, and it is easy to solve this problem. Create a special directory in the root directory of Git workspace gitignore files, and then fill in the file names to be ignored, and Git will automatically ignore these files.

There is no need to write from scratch gitignore file, GitHub has prepared various configuration files for us, which can be used only by combining them. All configuration files can be browsed directly online: https://github.com/github/gitignore

The principle of ignoring files is:

  1. Ignore the files automatically generated by the operating system, such as thumbnails;
  2. Ignore the intermediate files and executable files generated by compilation, that is, if a file is automatically generated through another file, it is not necessary to put the automatically generated files into the version library, such as those generated by Java compilation class file;
  3. Ignore your own configuration files with sensitive information, such as those that store passwords.

example:

Python compilation is ignored pyc,. pyo, dist and other files or directories:

# Python:
*.py[cod]
*.so
*.egg
*.egg-info
dist
build

Add your own definition of the file, and finally get a complete one gitignore file, as follows:

# Python:
*.py[cod]
*.so
*.egg
*.egg-info
*$py.class
dist
build
__pycache__
migrations
!migrations/__init__.py


# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3

# Jupyter Notebook
.ipynb_checkpoints
# Pycharm
.idea

The last step is to put the Gitignore is also submitted to Git, and it is completed! Of course The standard of gitignore is whether the git status command means working directory clean.

Sometimes, you want to add a file to Git, but you find that you can't add it because the file is deleted gitignore ignored:

$ git add hello.pyc
The following paths are ignored by one of your .gitignore files:
hello.pyc
Use -f if you really want to add them.

If you really want to add this file, you can use - f to force it to Git:

$ git add -f hello.pyc

Or you find out, maybe There is something wrong with gitignore. You need to find out which rule is wrong. You can use git check ignore command to check:

$ git check-ignore -v hello.pyc
.gitignore:2:*.py[cod]  hello.pyc

Git will tell us The third line rule of gitignore ignores the file, so we can know which rule should be revised.

Summary

  • When ignoring some files, you need to write gitignore;
  • The. gitignore file itself should be put into the version library and can be used for gitignore version management!

Configure alias

Do you often type the wrong command? Like git status? The word status is really hard to remember.

If clicking git st means git status, it will be much simpler. Of course, we strongly agree with this lazy method.

We just need to type a command and tell Git. Then st means status:

$ git config --global alias.st status

OK, now click git st to see the effect.

Of course, there are other commands that can be abbreviated. Many people use co for checkout, ci for commit, and br for branch:

$ git config --global alias.co checkout
$ git config --global alias.ci commit
$ git config --global alias.br branch

Later submission can be abbreviated as:

$ git ci -m "bala bala bala..."

--The global parameter is a global parameter, that is, these commands are useful in all Git warehouses on this computer.

stay Undo modification In the section, we know that the command git reset HEAD file can undo the modification of the temporary storage area and put it back into the working area. Since unstage is an operation, you can configure an alias:

$ git config --global alias.unstage 'reset HEAD'

When you type the command:

$ git unstage test.py

What Git actually does is:

$ git reset HEAD test.py

Configure a git last to display the last submission information:

$ git config --global alias.last 'log -1'

In this way, the latest submission can be displayed with git last:

$ git last
commit ac358082b6694ba923c293828a54b4115c6efcb0 (HEAD -> dev, origin/dev)
Merge: 003e6ed 5bd8a63
Author: junxi <xinlei3166@126.com>
Date:   Mon Mar 19 17:21:02 2018 +0800

    merge & fix hello.py

Some even madly configured lg to:

git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"

Let's see the effect of git lg:

mage-20180320121056

Why didn't you tell me earlier? Don't get excited. I'm not trying to remember more English words!

configuration file

When configuring Git, add -- global to work for the current user. If not, it only works for the current warehouse.

Where is the configuration file? The GIT configuration file of each warehouse is placed in In git/config file:

$ pwd
/Users/junxi/gitskills
$ cat .git/config 
[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true
    ignorecase = true
    precomposeunicode = true
[remote "origin"]
    url = git@github.com:junxi3166/gitskills.git
    fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
    remote = origin
    merge = refs/heads/master
[branch "dev"]
    remote = origin
    merge = refs/heads/dev

The alias is right after [alias]. To delete the alias, delete the corresponding line directly.

The Git configuration file of the current user is placed in a hidden file in the user's home directory In gitconfig:

$ cat ~/.gitconfig 
[user]
    email = xxx@126.com
    name = junxi
    signingkey = 4776DFA6E0FEBB24F9A70A49C722C757D7AF8BF3
[color]
    ui = true
[core]
    autocrlf = input
[filter "lfs"]
    clean = git-lfs clean -- %f
    smudge = git-lfs smudge -- %f
    process = git-lfs filter-process
    required = true
[alias]
    st = status
    last = log -1
    lg = log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit

You can also modify this file directly to configure the alias. If you make a mistake, you can delete the file and configure it again through the command.

Summary

By configuring Git with an alias, you can be lazy when entering commands. We encourage laziness.

Delete file

If you want to remove a file from version control and keep the local file, you first need to add this file to the gitignore file. Then execute the following command.

git rm file_path --cached

The above command will delete the file_ The file represented by path is deleted from version control, and the local file is retained. In addition, the file on the server side can be deleted only by commit ting. If you want to delete a folder from version control and keep local files, just add the - r parameter to the above command, that is

git rm -r folder_path --cached

If you want to delete all files in gitignore from version control, you need to execute the following two commands: remove all files first, and then add all files (the files in gitignore will be ignored this time).

git rm -r . --cached
git add .

Come to an end.

Keywords: git github server IDE

Added by amir1985 on Sun, 13 Feb 2022 12:51:18 +0200