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:
- 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
- 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 --all
orgit 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 areagit diff --cached
: used to see the difference between the staging area and the previous commitgit diff HEAD
: used to show the difference between the workspace and the last commitgit 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 submissionsgit log -<number>
: Displays the latest n submissionsgit log -p
: displays each log commit and each changegit log --stat
: displays brief statistics for each log committed and each change madegit log --oneline
: Displays a line of brief informationgit 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 changegit show <commit-id>
: used to show changes for a specific commitgit 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
.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.gitignoregit 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 filegit checkout .
: Deletes all filesgit 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 warehouseHEAD
Pointer positions, workspace and staging changes are unchanged--mixed
Move:HEAD
Pointer position and use rollback to version to reset the staging area, workspace modifications remain unchanged--hard
Move:HEAD
Pointer 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 commitgit revert -n <commit-id>
: Resets the target commit, but instead of creating a new commit, changes the workspace and staging areagit 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 branchesgit branch -r
: List all remote branches (more on remote branches later)git branch -a
: Lists all local and remote branchesgit 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 branchgit checkout -b <branch-name>
: Creates a branch and switches branchesgit checkout <branch-name>
: Switch branchesgit checkout -
: Switches to the previous branchgit 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 branchgit cherry-pick <branch-name>
: selects the latest commit for the specified branchgit 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-pickgit cherry-pick --quit
: Exits the operation and retains the current progressgit 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 tagsgit tag -l <tag-name>
: Filters the corresponding tagsgit tag --points-at <commit-id>
: View all tags on a commitgit show <tag-name>
: View a taggit 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 commitgit tag -a <tag-name> -m <message>
: Add a tag and messagegit 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 staginggit 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 historygit 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 storegit stash apply <number>
: Fetch the target ephemeralgit 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 recordgit 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 savegit stash drop <number>
: Deletes the target staginggit 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
orpick
: Do not change the commitr
orreword
: Preserves the commit, but changes the commit informatione
oredit
: Edit commit, similar to amends
orsquash
: merges the previous COMMIT and edits the new commitf
orfixup
: Merges with the previous COMMIT, using information from the previous commitd
ordrop
Delete 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 namegit 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 repositorygit remote -v
: Displays information about the remote warehousegit remote remove <remote-name>
: Deletes a remote repositorygit 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-u
parametergit push <remote-name> <tag-name>
: Pushes the specified tag to the remote endgit 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 updatesgit 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