preface

As a programmer 👨💻, Git can be said to be a necessary skill; However, most of the knowledge of Git is still limited to a few basic commands, or the use of graphical tools for daily operations (I have to say that git comes with IDE is a great use to use), so this article will hopefully give you a more comprehensive understanding of Git.

Git version 2.18.0 is used for the examples in this article, and the command effect may vary from version to version

A quick lookup of all the commands covered in this article

Tell Git who you are

Git usually lets you configure two basic pieces of information after installation:

git congfig user.name "xxxx" --global
git config user.email "[email protected]" -global
Copy the code

The above two commands are used to configure the user name and user email globally, which can be used to carry the comment information when submitting the warehouse, and track who made the modification and submission

In Git, configuration files have three scopes: local, global, and system. The system scope applies to all users of the current computer, global applies to the current user, and local applies only to a repository. Local is special compared to the other two scopes, because it is targeted ata warehouse, so it is required to run this command in the path of a warehouse, otherwise it will cause fatal: — Local can only be used inside a Git repository.

Command to view different scope configuration items:

git config --list --local
git config --list --global
git config --list --system
Copy the code

Since configuration files have different scopes, different scopes must also have different priorities; The priority order in Git is local > global > system; This means that if I set user.name to “global name” in the global scope and set user.name to “local name” in the local scope of a repository, then in subsequent commits, User. name will use local name.

Run through basic processes

After you have configured your information, start the actual Git-related operations

Initialize the warehouse

In order to use git related commands, you must be in a Git repository, so the first step is to initialize a Git repository, generally including two ways:

  1. Create a New Git repository in an existing project
cd <project-path>
▶ git init

Initialized empty Git repository in /xx/xx/.git/
Copy the code
  1. Create a new project and add the Git repository at the same time
▶ git init <project-path>

Initialized empty Git repository in /xx/xx/.git/
Copy the code

File status

In Git, there are roughly four types of file states:

  • Untraked: untracked file (Git only records changes to tracked files)
  • Unmodified: An Unmodified file that has been tracked by Git but has not changed since the last commit
  • Modified: A file that has been traced by Git but has changed since its last commit
  • Staged: Files that have been stored by Git

Lifecycle of a project file’s basic state in Git is shown below, preferably in conjunction with what follows.

After initializing the Git repository, you can run the git status command to check its status

▶ git status

On branch master
No commits yet
nothing to commit (create/copy files and use "git add" to track)
Copy the code

Git add: “git add” : “git add” : “git add” : “git add” : “git add” : “git add” : “git add” : “git add” : “git add” : “git add” :

▶ touch readme. TXT ▶ git status On branch master No commits yet Untracked files: (use"git add <file>..." to include in what will be committed)
  
        readme.txt
    
nothing added to commit but untracked files present (use "git add" to track)
Copy the code

The readme. TXT file is Untracked. Add the file to the staging area using git add readme. TXT (a concept explained later) and then check the state of the repository:

▶ git add readme. TXT ▶ git status On branch master No commits yet Changes to be: (use"git rm --cached <file>..." to unstage)

        new file:   readme.txt
        
Copy the code

Next, use git commit -m ”

” to commit the changes to the local repository:

▶ git commit -m "create readme.txt"[master (root-commit) 40cb86b] create readme.txt 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 readme. TXT ▶ git status On branch master nothing to commit, working tree cleanCopy the code

The readme. TXT file is now the Staged state, where the 40CB86b string is the ids (unique ids for each submission). Since the readme. TXT file in the workspace has not been modified, it is also in the Unmodified state. If the contents of the readme. TXT file are changed and git add and git commit operations are not performed, The readme.txt will be Modified:

echo "hello git"> readme. TXT ▶ git status On branch master Changes not stagedfor commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   readme.txt

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

Copy the code

You can commit your changes by repeating git add and git commit.

Git keeps a record of your changes, so you can use git log to see which changes were committed:

▶ git log

commit 832b59c98986a04cb8008f1eb39333504729dc45 (HEAD -> master)
Author: wenjun <[email protected]>
Date:   Wed Sep 18 00:00:51 2019 +0800

    add new line in readme.txt

commit 40cb86b7830e0606897d0f792f1a332fe74f5037
Author: wenjun <[email protected]>
Date:   Tue Sep 17 23:44:29 2019 +0800

    create readme.txt
Copy the code

The git log command prints out the commit ID, committer, and commit time.

Git status, git add, git commit, git log

Three regions

In git, we will introduce some important concepts, such as staging area and workspace. In Git, there are three areas: workspace, staging, and repository. The workspace is the directory area where the project is located (you can see the area in the project project), the repository is the area where all submissions are stored, and the staging area is the transition area between the workspace and the repository, which can simply be thought of as the area where changes to files that need to be committed are stored.

The git add command commits your changes to the staging area, and then the git commit command commits your changes to the staging area, which is clean. And if the workspace is not updated at this point, then the workspace is nothing to commit (working tree clean).

Not every change must be a git add and git commit. You can make it multiple times, use git add multiple times, and commit it all at once with git commit.

First, we’ll make some more changes in the readme. TXT file and use git add to put it in the staging area. Create a new chapter1.txt file and add it to the staging area with git add. Finally, commit both changes using the git commit command. So let’s see what happens?

▶ 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.txt

no changes added to commit (use "git add" and/or "git commit -a"▶ git add readme. TXT ▶ git status On branch master Changes to be committed: (use"git reset HEAD <file>..." to unstage)

        modified:   readme.txt

Untracked files:
  (use "git add <file>..." to include inChapter1. TXT ▶ git add chapter1. TXT ▶ git status On branch master Changes to be committed: (use"git reset HEAD <file>..."To unstage) new file: chapter1.txt Modified: readme. TXT ▶ git commit -m"modify readme.txt & create chapter1.txt"[master 640029f] modify readme.txt & create chapter1.txt 2 files changed, 1 insertion(+) create mode 100644 CHAPter1. TXT ▶ git status On branch master nothing to commit, working tree cleanCopy the code

Git will tell you that the readme. TXT file has been modified and can be submitted to the staging area. Git will remind you of two changes in the staging area when chapter1.txt is created and committed to the staging area, but chapter1.txt is not tracked by Git. When both changes are committed, the workspace is clean.

This is the basic process of git’s three regions. Some may ask: Why do staging areas exist at all? Why not commit directly from the workspace to the repository, which would be simpler and more convenient? In fact, the staging area seems to make git’s structure more complex, but it is the existence of staging area that makes us more flexible to save changes. For example, usually we want each submission to be pure and do only one thing, so that code review or version rollback will be clearer; However, we may enter A state of high efficiency and concentration by writing code, and complete function A and function B at once (assuming that the two functions do not overlap). At this time, we can add the code of function A to the temporary storage area and submit it, and then submit function B. If there is no staging area and either no commit or all commit, this may be more difficult to achieve.

Learn more commands

Through the previous content, about the basic git process over, but also about some basic commands; This section continues with a deeper understanding of git’s more common processes and commands (which I won’t go too far with).

Commit changes

git add

The previous git add command was used to add one file at a time. If you need more than one file you can use:

  • git add -u
  • git add --allorgit add .

Git add-u commits only changes to files that have been tracked. For example, we can modify the contents of readme. TXT and chapter1.txt at the same time, and create a new chapter2.txt. Git add -u will only commit the readme. TXT and chapter1.txt changes to the staging area

▶ 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:   chapter1.txt
        modified:   readme.txt

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

        chapter2.txt

no changes added to commit (use "git add" and/or "git commit -a"▶ git add -u ▶ git status On branch master Changes to be committed: (use"git reset HEAD <file>..." to unstage)

        modified:   chapter1.txt
        modified:   readme.txt

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

        chapter2.txt
        
Copy the code

Git add — The all and git add. Commands are equivalent and commit all changes, regardless of whether the file is tracked by Git or not. Again, the above example is a reference

▶ 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:   chapter1.txt
        modified:   readme.txt

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

        chapter2.txt

no changes added to commit (use "git add" and/or "git commit -a"▶ git add. ▶ git status On branch master Changes to be committed: (use"git reset HEAD <file>..." to unstage)

        modified:   chapter1.txt
        new file:   chapter2.txt
        modified:   readme.txt
        
Copy the code

If you change multiple areas in the same file but want to commit them separately, you can use git add -p for more detailed control (this command also takes you to a vim interface). We added two lines to readme.txt and committed two lines in two separate installments

Readme.txt has two more lines changed▶ cat readme. TXT hello git get furtheringit use git commit --amend ----------------------------- this is first line ----------------------------- this is second  lineThe readme.txt file will be printed first▶ git add -p diff --git a/readme.txt b/readme.txt index 84790cd.. Cf524cc 100644 -- a/readme.txt +++ b/readme.txt @@-1,4 +1,10 @@hello git get furtherin git

-use git commit --amend
\ No newline at end of file
+use git commit --amend
+
+-----------------------------
+this is first line
+
+-----------------------------
+this is second line
\ No newline at end of file
Use different commands to perform different operations. Choice? You can view the description of each commandStage this hunk [y,n,q,a,d,e,?] ? e# Enter the vim interface, there will be an explanation at the bottom of the operation and modification, at this point we just need to submit the first line of content, directly delete the content below the first line and save it
Manual hunk edit mode -- see bottom for@@ -1,4 +1,10 @@ hello git get furtherin git

-use git commit --amend
\ No newline at end of file
+use git commit --amend
+
+-----------------------------
+this is first line
+
+-----------------------------
+this is second line
\ No newline at end of file
# -- -- --
# To remove '-' lines, make them ' ' lines (context).
# To remove '+' lines, delete them.
# Lines starting with # will be removed.
#
# If the patch applies cleanly, the edited hunk will immediately be
# marked for staging.
# If it does not apply cleanly, you will be given an opportunity to
# edit again. If all lines of the hunk are removed, then the edit is
# aborted and the hunk is left unchanged.

You can see that part of the readme.txt changes have already been committed to the staging area
▶ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   readme.txt

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.txt
Copy the code

git commit

Git commit -a -m git commit -m git commit -m git commit -m git commit -m So it’s obvious that the files it submits are already tracked by Git. For the specification of commit messages, please refer to Ruan Yifeng’s article: A Guide to Writing Commit Messages and Change Logs

Git commit — Amend recommits the last commit and can add new changes. For example, you can use this command to modify the last commit if only the readme.txt changes were included in the last commit and chapter1.txt changes were not included

▶ 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:   chapter1.txt
        modified:   readme.txt

no changes added to commit (use "git add" and/or "git commit -a") ▶ git add readme. TXT ▶ git commit --m"only commit readme.txt"[master d5ffbec] only commit readme. TXT 1 file changed, 3 insertions(+), 1 deletion(-) ▶ gitlog --oneline
Note the commit ID at this point
d5ffbec (HEAD -> master) only commit readme.txt
640029f modify readme.txt & create chapter1.txt
832b59c add new line inTXT 40cb86b create readme. TXT ▶ git add. ▶ git status On branch master Changes to be committed: (use"git reset HEAD <file>..."Amend [master b15b67f] only commit readme.txt Date: Thu Sep 19 01:45:12 2019 +0800 2 files changed, 4 insertions(+), 1 deletion(-) ▶ gitlog --oneline
This is a change from the previous commit, but the commit ID is different now
cd52b05 (HEAD -> master) commit readme.txt & chapter1.txt
640029f modify readme.txt & create chapter1.txt
832b59c add new line in readme.txt
40cb86b create readme.txt

Copy the code

Git Commit — Amend brings you to a Vim interface where the first line is the previous Commit message and the information of the file to be committed below. You can modify the new COMMIT Message or leave it unchanged

only commit readme.txt

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Date: Thu Sep 19 01:45:12 2019 +0800
#
# On branch master
# Changes to be committed:
# modified: chapter1.txt
# modified: readme.txt
#
~
Copy the code

If you don’t need to modify the last commit message, you can use git commit –amend –no-edit to keep the previous message without entering the Vim interface. (Actually, if you use git commit and do not add -m, you will also enter vim interface to add commit message)

View submission History

git diff

As we continue to add, commit; Git diff: git add -p git diff: git add -p git diff: git add -p git diff

  • git diff: Used to see the difference between a workspace and a staging area
  • git diff --cached: used to see the difference between the staging area and the previous commit
  • git diff HEAD: used to show the difference between the workspace and the last commit
  • git diff <commit-id> <commit-id>: used to show the difference between two commits
▶ git status
# Make changes to readme.txt
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.txt

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


▶ git diff
Lines beginning with the # plus sign indicate newly added lines, and lines beginning with the minus sign indicate deleted lines
Git diff HEADdiff --git a/readme.txt b/readme.txt index cf524cc.. 267e34f 100644 --a /readme.txt +++ + b/readme.txt @@-7 4 +7 7 @@use git commit --amend this is the first line ----------------------------- -this is second line \ No newline at end of file +this is second line + + +change again \ No newline at end of file (END)No changes have been made to the staging area since the last commit▶ git diff --cached ▶ git add. ▶ git diff --cached# now the staging area and the last modification are the same as beforediff --git a/readme.txt b/readme.txt index cf524cc.. 267e34f 100644 --a /readme.txt +++ + b/readme.txt @@-7 4 +7 7 @@use git commit --amend this is the first line ----------------------------- -this is second line \ No newline at end of file +this is second line + + +change again \ No newline at end of file (END)Copy the code

Git diff allows you to see the difference between different regions directly, but the command line is not very intuitive. In this case, it is recommended to use a graphical interface to view the difference.

git log

The git log command is used to view the commit history.

  • git log: Used to view all submissions
  • git log -<number>: Displays the latest n submissions
  • git log -p: displays each log commit and each change
  • git log --stat: displays brief statistics for each log committed and each change made
  • git log --oneline: Displays a line of brief information
  • git log --graph: Display with simple graphics
▶ git log --oneline

c22c913efa87642532eccc264cfcb6b3318506f9 (HEAD -> master) commit the rest part
1cf3c61d3c1de7e6b4225c1b96f3e1a75313144d partial commit
a8b85b8054510688602bb3c7736205e539303d56 commit readme.txt & chapter1.txt
640029f6f64ced21f8588236217a788beae9ac44 modify readme.txt & create chapter1.txt
832b59c98986a04cb8008f1eb39333504729dc45 add new line in readme.txt
40cb86b7830e0606897d0f792f1a332fe74f5037 create readme.txt

Copy the code

Of course, a graphical interface is still recommended

git show

If we want to see what a commit does, git show is the place to go.

  • git show: is used to display the last committed change
  • git show <commit-id>: used to show changes for a specific commit
  • git show --name-only <commit-id>: The file name used to display a particular committed change
▶ git show - name - only a8b85b8054510688602bb3c7736205e539303d56 commit a8b85b8054510688602bb3c7736205e539303d56 Author: wenjun <[email protected]> Date: Thu Sep 19 01:45:12 2019 +0800 commit readme.txt & chapter1.txt chapter1.txt readme.txt (END)Copy the code

No doubt, this is still recommended to use the graphical interface

File delete & secure rename & ignore

git rm

All of these tutorials are about adding files to Git, but we don’t always add, we also need subtraction.

  • git rm <file-name>: Deletes files from workspace and removes trace of a file from repository (To be exact, just remove the file from the staging area, and the commit history of the repository will still retain the file)
  • git rm --cached <file-name>: Only removes tracing for the file, but still keeps the file in the workspace
# git rm = rm &&git add
▶ git rm chapter1.txt

rm 'chapter1.txt'


▶ git status
# chapter1.txt was removed from workspace
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        deleted:    chapter1.txt


Restore chapter1.txt first, try another command
▶ git rm --cached chapter1.txt
rm 'chapter1.txt'

▶ git status
# You can clearly see the difference between the previous command, which removes the trace for chapter1.txt in the staging area, so there is a deleted change (compared to the last commit); In this case, the status of workspace chapter1.txt is untraced
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        deleted:    chapter1.txt

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

        chapter1.txt


Copy the code

git mv

In general, there is nothing wrong with renaming files, and Git will be able to correctly infer the changes you have made

# change chapter1.txt to chapter12.txt
Chapter1.txt was deleted and chapter12.txt was created
▶ 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:    chapter1.txt

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

        chapter12.txt

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

Git will still correctly recommend renaming after committing to the staging area▶ git add. ▶ git status On branch master Changes to be committed: (use"git reset HEAD <file>..." to unstage)

        renamed:    chapter1.txt -> chapter12.txt
Copy the code

If we just change the case of the file name, it’s a different story:

# change chapter1.txt to chapter1.txt
# Git has not detected any changes
▶ git status
On branch master
nothing to commit, working tree clean

Git still considers the chapter1.txt file to have 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:   chapter1.txt

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

Git mv

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

        renamed:    chapter1.txt -> CHAPTER1.txt
Copy the code

Git mv
= mv
, git rm –cached , git add

.gitignore

Not all files in a project need to be tracked with Git. Often what you really need to track is the source code. You don’t need to track the packaged build files and you don’t want them to be Untracked all the time. You can create a.gitignore file at the root of your project to tell Git which files don’t need to be traced.

.gitignore Basic rules:

  • All blank lines or#The leading lines are ignored
  • *Stands for 0 or more arbitrary characters
  • ?The value contains 1 arbitrary character
  • [abc]Match any of them[]The characters in
  • /On behalf of the directory
  • 支那Any multi-level intermediate directory
  • !On behalf of the invert

Gitignore file example

# Stop looking, this is a comment

# ignore all.txt files
*.txt

# but index.txt is an exception! 1.txtJs files in the root directory are ignored only, if sub/index.js is ignored
/index.js

Ignore all files in the build directory
build/

# ignore index.js in any directory hierarchy below SRC
src/**/index.js
Copy the code

A common scenario is that a traced file needs to be ignored using.gitignore. For example, if a.gitignore rule is added to the.log file, git will not ignore the.log modification.

You need to first remove git’s tracking of the file, use git rm –cached, and commit the changes. The new rules will come into effect.

git clean

  • git clean: Deletes all files that are not tracked by Git, but not files ignored in.gitignore
  • git clean -n: Prints the name of the file to be deleted, but does not actually delete it
# We will prepare two untraced files other. TXT and index. TXT in the project. But index.txt is ignored by.gitignore
# prompt will only delete other.txt
▶ git clean -n                      
Would remove other.txt
Copy the code

Undo the changes and roll back the code

To err is human, to err is human. Fortunately, Git gives us a chance to regret it.

git checkout

Now, we’ve changed some code in the workspace and haven’t pushed git Add to the staging area yet. But suddenly didn’t want to change the workspace (capricious); You can undo workspace changes using the Git checkout command

  • git checkout <file-name>: Deletes a file
  • git checkout .: Deletes all files
  • git checkout <commit-id> <file-name>: restores the specified files of a COMMIT to the staging area and workspace (Your current workspace staging will be forcibly restored regardless of whether there is an update, so use it with caution)
▶ 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:   chapter1.txt
        modified:   readme.txt

no changes added to commit (use "git add" and/or "git commit -a") ▶ git checkout chapter1. TXT ▶ git status On branch master Changes not stagedfor commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   readme.txt

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

Git Checkout doesn’t stop there, but I’ll cover that later

git reset

Git reset HEAD

Git reset HEAD

Git reset HEAD

git reset HEAD

git reset HEAD




The change has been pushed to the staging area
▶ git stauts

On branch master
Changes to be committed:
  (use "git reset HEAD <file>..."TXT ▶ git reset HEAD readme.txt Unstaged changes after reset: M readme.txtThe change is rolled back to the workspace
▶ 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.txt

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

The HEAD keyword appears here, which represents the current version of the repository (not necessarily the latest version); The following chapter will explain in detail

In addition to being able to undo staging changes and roll back versions, you can also use this command to go back to the status of a commit. Git reset

. This command has three modes –soft, –hard, –mixed (default mode).

  • --soft: Only move the warehouseHEADPointer positions, workspace and staging changes are unchanged
  • --mixedMove:HEADPointer position and use rollback to version to reset the staging area, workspace modifications remain unchanged
  • --hardMove:HEADPointer position, and resets the workspace and staging area with rollback to version, keeping it consistent with the specified commit

It’s easy to get confused by the direct difference between these three modes, but the difference is as simple as the above

Take a look at the current submissions
▶ git log --oneline 

The three commits from '23bcc3e' to '93127f0' create a new line in readme.txt
9c127f0 (HEAD -> master) add third line in readme.txt
ff29824 add second line in readme.txt
23bcc3e add first line in readme.txt
a84a18c add .gitignore

# Now we want to go back to the '23bCC3e' submission
# commit id # commit id
▶ git reset --soft 23bcc3e  
▶ git log --oneline 
You can see that the current version has successfully returned to '23bCC3e'
23bcc3e (HEAD -> master) add first line in readme.txt
a84a18c add .gitignore

# Since soft mode was used, only the HEAD pointer was moved, so the workspace and staging area did not change before, but due to the HEAD pointer change, the current warehouse state and staging area appeared to be different
▶ git status

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

        modified:   readme.txt



Try hard mode now
▶ git reset --hard 9c127f0 

HEAD is now at 9c127f0 add third line inThe readme.txt ▶ gitlog --oneline 

The warehouse state is back to the original version
9c127f0 (HEAD -> master) add third line in readme.txt
ff29824 add second line in readme.txt
23bcc3e add first line in readme.txt
a84a18c add .gitignore

And since hard mode forces the workspace and staging area to be reset to match the HEAD state, the workspace is clean
▶ git status  

On branch master
nothing to commit, working tree clean

# Now use mixed mode before returning to '23bcc3e'
# mixed is the default, so you don't need to add --mixed
▶ git reset 23bcc3e  
▶ git status    

# Since the mixed mode was used, the HEAD pointer was moved and the staging area was reset, so the warehouse state and staging area did not change before, while the workspace and staging area were different
Compare with the previous soft mode to see the difference
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.txt

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

Git log will only print the commit pointed to by the HEAD pointer and all commits before it. As long as you remember the commit ID, you can go back again, as in the hard mode above, but if you don’t remember the ID, you can use git reflog, which prints the commit ID of your most recent action

▶ git reflog  

23bcc3e (HEAD -> master) HEAD@{0}: reset: moving to 23bcc3e
9c127f0 HEAD@{1}: reset: moving to 9c127f0
23bcc3e (HEAD -> master) HEAD@{2}: reset: moving to 23bcc3e
9c127f0 HEAD@{3}: reset: moving to 9c127f08158bac02b3ce9456160fbc3bcf8ed078
ff29824 HEAD@{4}: reset: moving to ff29824a23747234d142b966889399d702443ab5
9c127f0 HEAD@{5}: commit: add third line in readme.txt
ff29824 HEAD@{6}: commit: add second line in readme.txt
23bcc3e (HEAD -> master) HEAD@{7}: commit (amend): add first line in readme.txt
4f251eb HEAD@{8}: commit (amend): add first line in readme.txt
5cbd51c HEAD@{9}: commit: add first line in readme.txt
a84a18c HEAD@{10}: commit (initial): add .gitignore
Copy the code

git revert

Git Reset allows you to go back to a certain version of a commit, but if you want to reset one of those commits, you need to use Git Revert, which creates a new commit to reset a previous commit (reverse).

  • git revert <commit-id>: Creates a new commit to reset the target commit
  • git revert -n <commit-id>: Resets the target commit, but instead of creating a new commit, changes the workspace and staging area
  • git revet <start-id>... <end-id>: resets multiple commits (not start-id, but end-id)
The vim window prompts you to enter a new message for submission
▶ git revert head          
[master 2c9da62] Revert "add third line in readme.txt"
 1 file changed, 1 insertion(+), 2 deletions(-)

▶ git log --oneline
If left unchanged, this is the default message format
2c9da62 (HEAD -> master) Revert "add third line in readme.txt"
9c127f0 add third line in readme.txt
ff29824 add second line in readme.txt
23bcc3e add first line in readme.txt
a84a18c add .gitignore
Copy the code

branch

In this section, we’ll start with one of git’s most important features: branching. Branching makes collaborative development easier. Everyone can work in their own branch without affecting each other. Different accounts on the same computer; When you’re done, merge all the work together.

The HEAD pointer, which points to the current repository version, was mentioned earlier. In fact, in the previous log printing, you can see a flag like 9c127f0 – (HEAD -> master) in the first line. The master branch is a branch that is created by default when we create a new Git repository. All of our previous changes were all changes in the master branch.

Here’s the first takeaway: Each reference within Git is organized as a one-way linked list to form a chain structure like the one shown above. Master,HEAD, and so on are a series of Pointers to different commits. The difference is that the master pointer always points to the latest commit node of the branch it is in, whereas the HEAD is the current repository version, so it can be moved to different nodes at will. The same commit node can have multiple Pointers to it.

Based on the above conclusion, we can see that creating a new branch is actually creating a pointer, and pushing forward from the node that the pointer points to is all the nodes of the current branch. All nodes of the Develop branch are e137e9b -> F5b32C8 -> C1C3DFE -> e088135

See the branch

  • git branch: Lists all local branches
  • git branch -r: List all remote branches (more on remote branches later)
  • git branch -a: Lists all local and remote branches
  • git branch -v: Displays branch details
# We'd like to see what branches are currently available locally
▶ git branch
The * at the beginning of the # line indicates which branch the current repository points to
* master


▶ git branch -v

* master 9c127f0 add third line in readme.txt
Copy the code

Create & Switch & Delete branches

  • git branch <branch-name>: New branch
  • git checkout -b <branch-name>: Creates a branch and switches branches
  • git checkout <branch-name>: Switch branches
  • git checkout -: Switches to the previous branch
  • git branch -d <branch-name>: Delete branches (for branches that have been merged)
  • git branch -D <branch-name>: Deletes branches (whether merged or not)
Create a second branch▶ Git branch second ▶ Git branch -V# You can see that the second branch has been created, which now only wants the same node as the master branch
* master 9c127f0 add third line in readme.txt
  second 9c127f0 add third line in readme.txt

Switch to the second branch
▶ git checkout second  
Switched to branch 'second'

Create a new branch
▶ git branch third
▶ git branch
  master
* second
  third

# delete branch
▶ git branch -D third  
Deleted branch third (was 9c127f0).
Copy the code

Branch merge

Git merge after everyone commits their work in different branches, they will eventually merge their work together, which is where you need to use git merge.

We now add a few commits to the second branch, and the history now looks like this: The second branch adds two commits, while the Master branch adds no new commits. So the second branch is now two commits ahead of the master branch (the little yellow 🏷 represents the HEAD pointer).

  • git merge <branch-name>: Separate the target branch to the current branch
First look at the state of the second branch readme.txt▶ cat readme. TXT This is first line this is second line this is third line this is added by second branch this is also added by second branch# We now want to merge the two updates on the second branch, first switching to the master branch
▶ git checkout master
Readme.txt in the master branch is not updated in the second branch
# This is what we said earlier about branches not affecting each other▶ cat readme. TXT This is the first line this is the second line this is the third line ▶ git merge second Updating 9c127f0.. a5e61dd Fast-forward readme.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)Copy the code

Now look at the state: the Master branch already points to the same commit as the branch branch. At this point you can see updates to the Second branch in the Master branch.

Git merge git merge git merge git merge git merge git merge git merge If the current branch merges the target branch and there is no commit after the target branch, then the target branch is directly upstream of the current branch. In this case, the merge only needs to move the pointer of the current branch to the latest commit of the target branch. In our case, we have two new commits on second, but no new commits on master, so second is directly upstream of master, and the master branch merges second by simply moving the pointer to Second.

Git merge –no–ff

git merge –no–ff

▶ git merge --no-ff second 
Merge made by the 'recursive' strategy.
 readme.txt | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
Copy the code

The warehouse state at this point looks like this: Create a merge commit to merge the second branch content.

If both branches change the same place, the merge will conflict. Now we add a new commit in the Master branch that changes in the same place as the new commit in the Second branch

▶ git merge second 
Git error
Auto-merging readme.txt
CONFLICT (content): Merge conflict in readme.txt
Automatic merge failed; fix conflicts and then commit the result.

What is readme. TXT▶ cat readme. TXT This is first line this is second line this is the third lineThe conflicting parts are shown below
Changes to the current master branch
<<<<<<< HEAD
this is added by master branch
# Second branch changes
=======
this is added by second branch
this is also added by second branch
>>>>>>> second
Copy the code

At this point, you need to handle the conflict manually, cut out the unnecessary parts, and then commit as normal.

But I believe that you will also feel that it is not worth watching, easy to make mistakes; And if there’s a lot of conflict, it’s a lot of work. For this reason, git’s graphical tools are still recommended, which have a very intuitive graphical interface for conflict resolution. The following is the built-in tool of WebStorm:

Git status after normal commit after conflict resolution:

Pick up the cherry

Sometimes, we don’t want to merge all of the update commits from other branches. Maybe we just need some of them. In this case, git cherry pick is required.

  • git cherry-pick <commit-id>: Selects a COMMIT and merges it into the current branch
  • git cherry-pick <branch-name>: selects the latest commit for the specified branch
  • git cherry-pick <start-comm-id>... <end-commit-id>: Selects consecutive commits (open left, close right, not start-commit)
  • git cherry-pick <start-commid-id>^... <end-commit-id>: Selects consecutive commits (left close, right close, including start-commit)

Git repository:

# add new line to the master branch
▶ git cherry-pick 469a80b44
[master 72ec082] add new line in readme.txt by second branch
 Date: Sun Sep 22 22:58:18 2019 +0800
 1 file changed, 3 insertions(+), 1 deletion(-)
Copy the code

State at this time:

If you encounter a conflict, use:

  • git cherry-pick --continue: After resolving the conflict, proceed to the next cherry-pick
  • git cherry-pick --quit: Exits the operation and retains the current progress
  • git cherry-pick --abort: Cancel this operation

On the Tag

In Git, a tag is a pointer, just like a branch or HEAD. Unlike them, however, a tag cannot move once it is identified as pointing to a commit; So it’s especially good for marking which submission corresponds to the version number, and it’s easy to find.

Since a tag can’t be changed once it’s identified, it’s relatively simple compared to branching.

Look at the tag

  • git tag: View all tags
  • git tag -l <tag-name>: Filters the corresponding tags
  • git tag --points-at <commit-id>: View all tags on a commit
  • git show <tag-name>: View a tag
  • git show-ref --tags: View all the tags and their corresponding Commits

Create and delete a tag

  • git tag <tag-name>New tag:
  • git tag <tag-name> <commit-id>: Creates a new tag in the specified commit
  • git tag -a <tag-name> -m <message>: Add a tag and message
  • git tag -d <tag-name>: remove the tag
Create a new tag at the specified COMMIT
▶ git tag v1.0 71019                                   

Create a new tag for the latest commit of the current branch
▶ git tag v2.0   

Print the current tag▶ git show - ref - 71019047 tags bf04999b475f23409b3158c4a728dfe7 refs/tags / 91 d4eb5400168f699bc33a19959daac89a068406 v1.0 Refs/tags/v2.0# remove the tag
▶ git tag -dV1.0 does tag'v1.0' (was 7101904)
Copy the code

For emergency stopper, use Stash

You’re working on a new feature in the feature branch and QA tells you there’s a bug in the Master branch that needs fixing. While your workspace is still half-finished, shunt will result in a local change message. If you create a new commit, it will not be a complete feature. At this point, use the git stash command to temporarily store your local changes.

The new stash

Git Stash temporarily stores all changes to the workspace and staging area, keeping the workspace and staging area consistent with the last commit.

Add some changes to the workspace and staging area first
▶ git status

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

        modified:   readme.txt

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes inTXT ▶ git stash Saved Working Directory and index state WIP on master: 91d4eb5 add sixth linein readme.txt by second branch

# Workspace and staging areas are clean
▶ git status

On branch master
nothing to commit, working tree clean

Copy the code

If stash messge is not specified separately, the default format will be WIP on

:



You can specify the messge information you want using git Stash Save

.

▶ git stash save "this is a temporary message"

Saved working directory and index state On master: this is a temporary message
Copy the code

The default scope of git stash is for files that have already been tracked, but you can also extend the scope with the following command:

  • git stash -u: Adds untraced files to the staging
  • git stash -a: Add all files to temporary storage (Even if the file is ignored by Git)

Look at the staging

  • git stash list: View the temporary history
  • git show stash@{<number>}: View a subspecific temporary store
▶ git stash list Stash @{0}: On master: this is a temporary message Stash @{1}: WIP On master: 91d4eb5 add sixth lineinReadme. TXT by second branch ▶ git show stash@{0}# Show the current Stash diffcommit 1efaf35f6e15fff0f6545dce28c95d11480d2a8c (refs/stash) Merge: 91d4eb5 4b8a600 Author: wenjun <[email protected]> Date: Mon Sep 23 17:19:01 2019 +0800 On master: this is a temporary message diff --cc readme.txt index 394b8bc,394b8bc.. Ac801af -- a/readme.txt +++ b/readme.txt @@@-3, 4-3,4 +3,7 @@@@this is second Lin this is third line this is added by second branch --this is also added by second branch ++this is also added by second branch ++ ++ ++yesCopy the code

Remove & Delete temporary storage

  • git stash apply: Retrieves the latest temporary store
  • git stash apply <number>: Fetch the target ephemeral
  • git stash pop: Take out the latest temporary storage,And delete the temporary record
▶ git stash apply          

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.txt

no changes added to commit (use "git add" and/or "git commit -a"▶ Git Stash List# Recent transient history still exists
stash@{0}: On master: this is a temporary message
stash@{1}: WIP on master: 91d4eb5 add sixth line inReadme.txt by Second Branch ▶ git Stash pop On Branch master Changes not stagedfor commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   readme.txt

no changes added to commit (use "git add" and/or "git commit -a") Dropped refs/stash @ {0} (1 efaf35f6e15fff0f6545dce28c95d11480d2a8c) ▶ git stash the listThe most recent temporary history has been deleted
stash@{0}: WIP on master: 91d4eb5 add sixth line in readme.txt by second branch
Copy the code

Instead of pulling the ephemera out directly, we can create a separate branch for the ephemera

  • git stash branch <branch-name>: Creates a new branch for the last staging and deletes the record
  • git stash branch <branch-name> <number>: Creates a new branch for the target staging and deletes the record
Create a new stash branch
▶ git stash branch stash-branch

Switched to a new branch 'stash-branch'
On branch stash-branch
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   readme.txt

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.txt

Dropped refs/stash@{0} (8ba8cdc6e530fc0c827f6f3c1978039dd2c19bc4)

You can see that the branch has been created and switched to a new branch▶ Git branch master second * stash- BranchCopy the code

Unwanted staging can be deleted using the following command:

  • git stash drop: Deletes the latest temporary save
  • git stash drop <number>: Deletes the target staging
  • git stash clear: Clear history

Rebase

Git has a super awesome operation called rebase. It sounds weird, but it’s a serious command. All we’ve talked about so far is how to roll back versions, how to undo changes. But there was no historical submission. Rebase can actually change historical commits and merge branches.

Merging branches

Git rebase merges branches with git rebase. Git rebase merges branches with git rebase. Use git rebase

.

Let’s take a look at the current git state. The master branch has one new commit and the second branch has two new commits

▶ git rebase second

First, rewinding head to replay your work on top of it...
Applying: add a.txt
Copy the code

Now the warehouse status is:

master
second

Git merge git merge

It is obvious that using rebase simultaneously results in a simpler commit history, which is why some people prefer to use Rebase.

Rewrite history

Git rebase -i

allows you to interactively manipulate all commits up to commi-id (excluding commits to which commit-id refers).

Amend, which I have learned before, is also a way to rewrite history

If we want to change the last three commits, rename add A.txt and merge the update readme.txt aagin and update readme.txt commits

▶ git rebase -i HEAD~3

pick 3baae50 update readme.txt
pick c951be0 update readme.txt again
pick 5a57f77 add a.txt

# Rebase 9c127f0.. 5a57f77 onto 9c127f0 (3 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# . create a merge commit using the original merge commit's
# . message (or the oneline, if no original merge commit was
# . specified). Use -c 
      
        to reword the commit message.
      
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
#
# Note that empty commits are commented out

Copy the code

And then it’s going to be like the Vim interface, where every commit we’re dealing with has the pick keyword in front of it. We can replace different keywords to achieve different effects:

  • p or pick: Do not change the commit
  • r or reword: Preserves the commit, but changes the commit information
  • e or edit: Edit commit, similar to amend
  • s or squash: merges the previous COMMIT and edits the new commit
  • f or fixup: Merges with the previous COMMIT, using information from the previous commit
  • d or dropDelete the commit (or delete the row directly, with the same effect)

Based on the effect we want, finally rewrite the keyword as:

pick 3baae50 update readme.txt
f c951be0 update readme.txt again
r 5a57f77 add a.txt
Copy the code

Then save the submission to get the desired effect:

If a conflict is needed during the rebase process, use:

  • Git rebase –continue: Proceed to the next operation (after conflict resolution)
  • Git rebase –skip: skip the current operation
  • Git rebase — Abort: Aborts the rebase operation

Rebase common operation tips

Put the original commit into the scope of rebase

Git rebase -i

git rebase -i

All general cases cannot be added to rebase by default for the first commit. You can add pick

in the first line of the VIm operation interface after running the command to include them


Merge several non-consecutive commits into one

Git rebase -i

and squash all commit operators except the first commit to be merged. Git rebase -i

Split a COMMIT into several

After using git rebase -i

, use git reset HEAD^ to reset all the more of the commit to the workspace. Finally, use git rebase –continue to complete the rebase operation

Easy operation to restore the state before Rebase

Git reset –hard

Before rebase starts, create a branch, perform various rebase operations, and use git reset –hard

to restore the original state

Remote warehouse

We before all of the content is based on the local repository, but now the git popularity is so high, not only because of its excellent version control, is inseparable from the support of remote warehouse, such as the world’s largest gay dating site making, because of the existence of remote operations, so we can amend the local pushed to the remote, It is also very convenient to pull updates submitted by others remotely.

Clone & Manage remote warehouses

If it is an existing remote repository and we want to download it locally, we can use:

  • git clone <url>: pull code and use the default remote repository name
  • git clone <url> <new-name>: : pull code, custom local warehouse name

For a repository like the one in this article that already has local submissions, you can create a new repository on Github, assign a link, and use:

  • git remote add <remote-name> <remote-url>: Adds a remote repository
  • git remote -v: Displays information about the remote warehouse
  • git remote remove <remote-name>: Deletes a remote repository
  • git remote rename <old-remote-name> <new-remote-name>: Renames the remote operation name
▶ git remote add origin [email protected]:AHOhhhh/git-practice. Git ▶ git remote -v origin [email protected]:AHOhhhh/git-practice.git (fetch) origin [email protected]:AHOhhhh/git-practice.git (push)Copy the code

Push and Update

  • git push <remote-name> <branch-name>: Push branches to a specific remote repository. If only one remote repository can be omitted, the first push needs to be added-uparameter
  • git push <remote-name> <tag-name>: Pushes the specified tag to the remote end
  • git push <remote-name> --tags: Pushes all tags to the remote end
Add '-u' to the file
▶ git push       
fatal: The current branch master has no upstream branch.
To push the current branch and setThe remote as upstream, use git push --set-upstream origin ▶ git push-u origin master Enumerating Objects: 15, done. Counting objects: 100% (15/15), done. Delta compression using up to 8 threads. Compressing objects: 100% (12/12), done. Writing objects: 100% (15/15) and 2.00 KiB | 1.00 MiB/s, done. Total 15 (delta 0), reused 0 (delta 0) To github.com:AHOhhhh/git-practice.git * [new branch] master -> master Branch'master' set up to track remote branch 'master' from 'origin'.

Push all branches to the remote end
The remote branch represents the corresponding remote branch
▶ git branch -a 

* master
  second
  remotes/origin/master
  remotes/origin/second

# push all tags· Git push -- Tags Total 0 (delta 0), FLUE 0 (delta 0) To github.com:AHOhhhh/ git-practic. git * [new tag] v1.0 -> v1.0Copy the code

When there are remote updates, you can use:

  • git fetch: Pull updates
  • git pull: gets remote warehouse updates and automatically merges them into local branches (equivalent togit fetch && git merge)
  • git pull --rebase: Pull updates using rebase (similar to merging local branches using rebase)
▶ Git pull remote: Enumerating Objects: 3, done. Remote: Counting Objects: 100% (3/3), done. Compressing objects: 100% (1/1), done. remote: Total 2 (delta 1), reused 2 (delta 1), pack-reused 0 Unpacking objects: 100% (2/2), done. From github.com:AHOhhhh/git-practice e771fff.. a8207fe master -> origin/master Updating e771fff.. a8207fe Fast-forward e.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 e.txtCopy the code

Special note: because the previous git commit –amend, rebase and other operations can change the commit history, it is best to only work on the local commit. Try not to do so for the commit that has been pushed to the remote, otherwise there will be a lot of differences and conflicts with the remote

conclusion

So far, the common operation of Git has been explained. Although the whole article is about the use of the command line, it does not mean that the author thinks that the command line is superior to the UI party. In fact, many pictures in the article are the result of using the graphical interface. However, using the graphical interface all the time, you will not understand many git commands deeply enough, resulting in some git errors always stumble.

Therefore, I hope that through this article, I can sort out the common knowledge points of Git, and hope that we can have a deeper understanding of Git, combined with the convenient operation of the graphical interface, so that the use of Git in the future can be more smooth.

More articles

  • Git is simpler than you think – Principles