Git usage and principles

Git usage and principles

I recently reviewed the previous notes and revised it a bit by the way, and found that I haven t updated the article for a long time, so I took it out and made up an article by the way.

1. Introduction

Git is currently the best version control system in the world.

Git was originally used to manage Linux source code and was developed by Linus.

  1. linux installation

    sudo apt-get install git

  2. mac install

    One is to install homebrew, and then install Git through homebrew. For specific methods, please refer to homebrew's documentation:

    $ Brew install git copy the code

    The second method is simpler and the recommended method is to install Xcode directly from the AppStore. Xcode integrates Git, but it is not installed by default. You need to run Xcode, select the menu "Xcode" -> "Preferences", and find it in the pop-up window "Downloads", select "Command Line Tools", and click "Install" to complete the installation.

  3. windows install git

    Using Git on Windows, you can download the installer directly from the official Git website, and then install it according to the default options.

Contrast between centralized and distributed

centralized: version library is centrally stored on the central server, and when you work, you use your own computer, so you must first obtain the latest version from the central server, and then start to work. Push your own live to the central server.

Features: 1, networking, local area network

distributed: First of all, the distributed version control system does not have a "central server" at all. Everyone's computer is a complete version library. Secondly, after the modification is completed, the modified content is pushed to the other party to achieve version control.

Distributed version control, due to some reasons (not accessible, etc.). Therefore, a distributed version control system usually also has a computer that acts as a "central server", but the role of this server is only to facilitate the "exchange" of everyone's modifications. Without it, everyone can work the same, but it is inconvenient to exchange and modify. That's it.

If you have 10 colleagues, you have to submit 10 changes for each change, and other colleagues have to submit their changes to us separately, so we simply find a fixed computer (server) to uniformly stipulate and push the changes to this A computer, so you only need to submit it once, and other people can synchronize on this machine.

The difference between centralized and distributed is:

  • Does your local have a complete repository history!
  • Assuming that the SVN server is gone, then you have lost all historical information, because your local only has the current version and some historical information.
  • Assuming that the GitHub server is gone, you will not lose any git history information, because you have complete repository information locally. You can re-upload the local git repository to another git service provider.

Choice of version control:

  • The storage of plain text such as code is suitable for git
  • Office and other binary files are suitable for SVN

Git does not support non-plain text content very well. Although it can manage versions, it cannot easily diff and merge.

Git generally supports text files better, but office documents such as word and excel are binary files. One scenario of using Git is that when multiple people edit a file at the same time, conflicts in file editing may occur. If it is a text file, you will see the changes made by everyone during the final merge, and the conflicts will also be marked, which will help you to repair the conflicts. The binary file does not have such a function. In fact, if it is an ordinary office document, you can use tools such as Youdao Cloud Assistance, Tencent Document, etc., which can mark out the modification traces of Word or other office documents.

All version control can only be aimed at text content, binary content like word, the so-called version is a file snapshot, you can t compare differences, you can only count as a backup network disk

2. create a version library

Repository, also known as warehouse, English name repository, you can simply understand it as a directory. All files in this directory can be managed by Git. Git can track the modification and deletion of each file, so that it can be tracked at any time. History, or it can be "restored" at some point in the future

  1. Create folder

    zbt:WorkSpace zbt$ mkdir learngit zbt:WorkSpace zbt$ cd learngit zbt:learngit zbt$ pwd /Users/zbt/Documents/WorkSpace/learngit //pwd displays the full name of the directory Copy code
  2. Initialize (create) the warehouse git init

    zbt:learngit zbt$ git init Initialized empty Git repository in/Users/zbt/Documents/WorkSpace/learngit/.git/ zbt:learngit zbt$ ls -ah . .. .git Copy code
  3. Add files to the repository git add xxx

    zbt:learngit zbt$ open readme.txt zbt:learngit zbt$ git add readme.txt Copy code
  4. Submit files git commit -m "explore"

    zbt:learngit zbt$ git commit -m "wrote a readme file" [master (root-commit) baf57ac] wrote a readme file 1 file changed, 1 insertion(+) create mode 100644 readme.txt The information you can see here is that the main warehouse has been submitted Copy code
  5. Modify and view the file git status/git diff

    zbt:learngit zbt$ git status On branch master nothing to commit, working tree clean zbt:learngit zbt$ open readme.txt zbt:learngit zbt$ 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 ------ diff --git a/readme.txt b/readme.txt index 01f4d2b..f1a8b98 100644 --- a/readme.txt +++ b/readme.txt @@ -1 +1,3 @@ -Git test /No newline at end of file +Git test + +Git second line /No newline at end of file zbt:learngit zbt$ Copy code
  6. Submit again

    zbt:learngit zbt$ git add readme.txt//(This command is necessary, because add is only responsible for adding changes at the time, regardless of the subsequent ones) zbt:learngit zbt$ git commit -m "second commit" [master c8225b5] second commit 1 file changed, 3 insertions(+), 1 deletion(-) Copy code

3. Version rollback

zbt:learngit zbt$ git log --pretty=oneline 5823e442831f54bbe6996afd7262d31bb5662152 (HEAD -> master) thrid commit c8225b571a416bcca9700cde70fa1cd71e9e172e second commit baf57ac7f2dff4411607688d255a259aa42f26c9 wrote a readme file Copy code

Unlike SVN, Git s commit id is not 1, 2, 3...incremental numbers, but a very large number calculated by SHA1, expressed in hexadecimal, and the commit id you see is the same as mine. It's definitely different, subject to your own.

zbt:learngit zbt$ git reset --hard HEAD^ HEAD is now at c8225b5 second commit zbt:learngit zbt$ open readme.txt zbt:learngit zbt$ git log --pretty=oneline c8225b571a416bcca9700cde70fa1cd71e9e172e (HEAD -> master) second commit baf57ac7f2dff4411607688d255a259aa42f26c9 wrote a readme file (The version pointed to by HEAD is the current version, so Git allows us to shuttle between the version history, using the command git reset --hard commit_id.) Copy code

You can see that the version is rolled back to the previous version.

zbt:learngit zbt$ git reset --hard 5823 HEAD is now at 5823e44 thrid commit zbt:learngit zbt$ git log --pretty=oneline 5823e442831f54bbe6996afd7262d31bb5662152 (HEAD -> master) thrid commit c8225b571a416bcca9700cde70fa1cd71e9e172e second commit baf57ac7f2dff4411607688d255a259aa42f26c9 wrote a readme file Copy code

Then if you want to go back to the bottom and submit here three times, then you need to know the commitid

zbt:learngit zbt$ git reset --hard 5823e HEAD is now at 5823e44 thrid commit zbt:learngit zbt$ Copy code

There is no need to write all the version numbers, just the first few digits, and Git will find them automatically. Of course, you can't just write the first one or two, because Git may find multiple version numbers, and you can't determine which one it is.

The Git version rollback speed is very fast, because Git has a HEAD pointer to the current version internally. When you roll back the version, Git just points the HEAD from the content of the second commit.

Git provides a command git reflog to record your every command git reflog 84b708a08 HEAD@{6}: merge origin/develop: Fast-forward 0946357c9 HEAD@{7}: reset: moving to HEAD 0946357c9 HEAD@{8}: commit: fix: APP-627 delay and switch tab to report to reduce the probability of this occurrence 3e7838651 HEAD@{9}: commit: fix: Copy code

Comparison of git reset and git revert:

If there is already A -> B -> C, I want to go back to B: Method 1: reset to B, lose C: A -> B --soft: Keep the source code, only roll back the commit information to a certain version, and does not involve the rollback of index (stage). If you still need to submit, just commit directly. --mixed: The source code will be kept, but the git commit and index information will be rolled back to a certain version. (The default of git reset is --mixed mode, that is, git reset is equivalent to git reset --mixed) --hard: The source code will also fall back to a certain version, and both commit and index will fall back to a certain version. (Note that this method will change the source code of the local code warehouse) Method 2: Submit another revert to reverse the modification and become B: A -> B -> C -> B C is still there, but the two Bs are duplicates Depending on your needs, maybe C just submitted it wrong (such as submitting the password) and must be reset If C is a modification, and you want to change it back now, you may change it to C in the future, then you just revert Copy code

4. work area and temporary storage area

Work area: directory of working files

Repository: There is a hidden directory .git in the workspace. This is not a workspace, but a Git repository.

There are many things in the Git repository, the most important of which is the staging area called stage (or index), the first branch master automatically created by Git for us, and a pointer to master called HEAD .

The first step is to add the file with git add, which is actually to add the file modification to the temporary storage area;

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

Because when we created the Git repository, Git automatically created the only master branch for us, so now, git commit is to submit changes to the master branch.

After we make changes to the file, use the add command and put the changes in the staging area (Stage)

After using the commit command, the modification is submitted from the staging area to the master branch

Management modification

If you make the first modification -> git add -> second modification -> git commit, in this case, only the modification of add will be submitted once. Because git commit is only responsible for committing the changes in the staging area to the branch. add is to put the modification into the temporary storage area.

Undo edit

The command git checkout - readme.txt means to undo all the modifications of the readme.txt file in the work area. There are two situations here:

One is that readme.txt has not been placed in the temporary storage area since it was modified. Now, if the modification is undone, it will return to the same state as the version library;

One is that after readme.txt has been added to the temporary storage area, it is modified. Now, undo the modification and return to the state after adding it to the temporary storage area.

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

The git checkout - file command is very important. Without --, it becomes a "switch to another branch" command. We will encounter the git checkout command again in the branch management later.

Use the command git reset HEAD to undo the modification of the temporary storage area (unstage) and put it back into the work area

In Android studio, you can use Rollback to put the changes in the temporary storage area into the work area and undo all the changes.

Delete Files
rm test.txt copy code

5. remote warehouse

Currently, there are many github, gitee, and aliyuncode in remote warehouses. Because the transmission between the local warehouse and the remote warehouse is encrypted through SSH. Then you need to set up SSH Key.

Step 1: Create SSH Key. In the user's home directory, check whether there is a .ssh directory. If so, check whether there are two files, id_rsa and, in this directory. If there are already, you can skip to the next step. If not, open Shell (open Git Bash under Windows) and create SSH Key:

$ Ssh-keygen -t rsa -C "" copy the code

You need to change the email address to your own email address, then press Enter all the way and use the default value. Since this key is not used for military purposes, there is no need to set a password.

If all goes well, you can find the .ssh directory in the user's home directory. There are two files, id_rsa and These two are the key pair of SSH Key. id_rsa is the private key and cannot be leaked out. It's a public key, so you can tell anyone with confidence.

Step 2: Log in to XXX and open the "Account settings", "SSH Keys" page. Then, click "Add SSH Key", fill in any Title, and paste the content of the file in the Key text box.

Why does GitHub need SSH Key? Because GitHub needs to recognize that the commits you push are indeed pushed by you, not by others, and Git supports the SSH protocol, so as long as GitHub knows your public key, you can confirm that only you can push.

Of course, GitHub allows you to add multiple keys. Assuming that you have several computers, you will submit at the company for a while, and submit at home for a while. As long as you add the Key of each computer to GitHub, you can push to GitHub on each computer.

Configure multiple ssh keys

# gitee Host HostName PreferredAuthentications publickey IdentityFile ~/.ssh/gitee_id_rsa # github Host HostName PreferredAuthentications publickey IdentityFile ~/.ssh/github_id_rsa It is best to add a user here USER Copy code
Add remote warehouse
  1. Log in to the account, then Create a new repo, fill in xxx in the Repository name, and keep the default settings for others. Click the "Create repository" button to successfully create a new Git remote repository.

  2. Then follow the generation steps to link the remote warehouse

    //or create a new repository on the command line//echo "# learngit" >> git init git add git commit -m "first commit" git branch -M main git remote add origin git push -u origin main

    //Or push an existing repository from the command line git remote add origin git branch -M main git push -u origin main

Push the contents of the local library to the remote, using the git push command, actually push the current branch master to the remote.

Since the remote library is empty, when we push the master branch for the first time, the -u parameter is added. Git will not only push the contents of the local master branch to the remote new master branch, but also the local master branch and the remote The master branch is linked, and the commands can be simplified in the future push or pull.

git push origin master copy the code

SSH warning When you connect to GitHub using Git's clone or push command for the first time, you will get a warning:

The authenticity of host' (xx.xx.xx.xx)' can't be established. RSA key fingerprint is xx.xx.xx.xx.xx. Are you sure you want to continue connecting (yes/no)? Copy code

This is because Git uses SSH connection. When SSH connection verifies the GitHub server's Key for the first time, you need to confirm whether the fingerprint information of GitHub's Key is really from the GitHub server. Just enter yes and press Enter.

Git will output a warning telling you that the GitHub Key has been added to a trust list on this machine:

Warning: Permanently added '' ( RSA) to the list of known hosts. Duplicated code

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

Clone from remote warehouse
git clone Cloning into'gitskills'... remote: Counting objects: 3, done. remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 3 Receiving objects: 100% (3/3), done. Copy code

6. branch management

Every time you commit and modify Git, the modified version will be connected into a timeline, and this timeline is a branch. The main branch is master. Strictly speaking, HEAD does not point to the commit, but to the master. The master points to the commit. Therefore, HEAD points to the current branch.

The difference between origin, HEAD and master

HEAD: Currently submit your repo. Most of the time, HEAD points to the latest commit in the branch.

master: The name of the default branch that git created for you when the repo was first created. In most cases, "main" means "main branch".

origin: The default name provided by git for the remote repository.

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

Git creates a branch very quickly, because apart from adding a dev pointer and changing the HEAD point, there is no change in the files in the workspace!

However, from now on, modifications and submissions to the workspace are for the dev branch. For example, after a new submission, the dev pointer moves one step forward, while the master pointer remains unchanged:

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

1. we create the dev branch, and then switch to the dev branch:

$ git checkout -b dev Switched to a new branch'dev' Copy code

The git checkout command plus the -b parameter means to create and switch, which is equivalent to the following two commands:

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

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

$ git branch * dev master Copy code

The git branch command will list all branches, and the current branch will be marked with an *.

Then, we can commit normally on the dev branch, for example, make a modification to readme.txt and add a line:

Creating a new branch is quick. Then submit:

$ git add readme.txt $ git commit -m "branch test" [dev b17d20e] branch test 1 file changed, 1 insertion(+) Copy code

Now that the work on the dev branch is complete, we can switch back to the master branch:

$ git checkout master Switched to branch'master' Copy code

After switching back to the master branch, check another readme.txt file, the content just added is gone! Because that commit was on the dev branch, and the commit point of the master branch at the moment has not changed:

Now, we merge the work of the dev branch to the master branch:

$ git merge dev Updating d46f35e..b17d20e Fast-forward readme.txt | 1 + Copy code
Rebase (rebase)
  • The rebase operation can organize the history of local unpushed fork submissions into a straight line;
  • The purpose of rebase is to make it easier for us to view the changes of historical submissions, because forked submissions require three-party comparison.

The git merge operation to merge branches will make each commit of the two branches sorted by commit time (not push time), and will merge the latest commit points of the two branches into a new commit, and the final branch tree will appear Non-entire linear form

The git rebase operation actually breaks all the commits of the current rebase branch based on the original branch commit point into a patch, and regenerates a new commit hash value, again based on the current latest commit point of the original branch Submissions are not sorted according to the actual time point of each submission on the two branches. After the rebase is completed, it will not generate a new commit point when switching to the base branch to merge another branch, which can keep the entire branch tree perfect Linear

It is also worth mentioning that when we develop a feature, there may be countless commits locally, but you actually only want to display one complete commit record after each functional test is completed on your master branch. , Other commit records do not want to be kept on your master branch in the future, then rebase will be a good choice, he can merge multiple local commits into one commit during rebase, and can also modify the description of the commit, etc.

Note: If the submissions exist outside your warehouse, and others may develop based on these submissions, then do not perform rebasing.

Rebasing vs. Merging

Which way is better?

There is a view that the submission history of a warehouse is to record what actually happened. It is a historical document, which is valuable in itself and cannot be changed randomly. From this perspective, changing the submission history is a kind of blasphemy, you use lies to cover up what actually happened. What if the commit history resulting from the merger is a mess?

Since this is the case, these traces should be preserved so that future generations can refer to them. Another view is just the opposite. They believe that the submission history is what happened during the project. No one will publish the first draft of a book, and the software maintenance manual also needs to be revised repeatedly in order to be easy to use. Those who hold this view will use tools such as rebase and filter-branch to write stories, and write them as they are convenient for later readers.

Git is a very powerful tool that allows you to do many things with commit history, but each team and each project has different requirements for this.

The general principle is to only perform rebasing operations to clean up the history of local modifications that have not been pushed or shared with others, and never perform rebasing operations on commits that have been pushed elsewhere. In this way, you can enjoy the convenience brought by the two methods.

git tag v1.0 git tag v0.9 f52c633 git push origin v1.0 git push origin --tags //View git tag //delete label git tag -d v0.9 git push origin :refs/tags/v0.9 Copy code

Note: By default, the git push command does not send tags to the remote warehouse server. After creating the label, you must explicitly push the label to the shared server. This process is like sharing a remote branch-you can run git push origin [tagname].

7. build a Git server

Ignore file.gitignore
Configure alias
git config --global checkout git config --global commit git config --global branch Copy code

Subsequent submissions can be abbreviated as:

git ci -m "bala bala bala ... " Copy the code
Create git steps
  1. Install git

    sudo apt-get install git copy the code
  2. Create a git user to run the git service:

    sudo adduser git Copy code
  3. Create certificate login:

    Collect the public keys of all users who need to log in, which is their own file, and import all public keys into the/home/git/.ssh/authorized_keys file, one per line. Copy code
  4. Initialize the Git repository:

    git init --bare sample.git Copy code

    Git will create a bare warehouse, which has no workspace. Because the Git warehouse on the server is purely for sharing, users are not allowed to log in to the server directly to change the workspace, and the Git warehouse on the server usually ends with .git . Then, change owner to git:

    sudo chown -R git:git sample.git Copy code
  5. Disable shell login

    For security reasons, the git user created in the second step is not allowed to log in to the shell. This can be done by editing the/etc/passwd file. Find a line similar to the following:

    git: x: 1001: 1001: ,,,:/home/git:/bin/bash duplicated code


    git: x: 1001: 1001: ,,,:/home/git:/usr/bin/git-shell duplicated code

    In this way, git users can use git through ssh normally, but cannot log in to the shell, because the git-shell specified for git users automatically exits every time they log in.

    What is a login shell: The login shell can be used for user login, such as/bin/bash,/bin/sh,/bin/csh... Generally, the default user shell in Linux is bash, which means you can log in Go in and write commands.

    shell login

    Non-login shell: The classic/bin/nologin is a non-login shell, which means that if a user defaults to it, the user cannot use Linux even if they log in to Linux.

    The shell is the medium of communication between the user and the computer. The login shell guarantees the communication between the user and the computer, and the non-login shell cannot allow the computer to communicate with the user.

    The default login shell for users is recorded in the/etc/passwd file.

    Non-login shell has its specific purpose, such as an ftp server built with linux and multiple users are created, then the default shell of these users can be changed to nologin. In this way, although these users are users on linux, Unable to log in to the linux host, you can only enter the ftp server, which also ensures safety!

  6. Clone a remote warehouse

    git clone git@server:/srv/sample.git Copy code
Manage public keys

If the team is small, it is feasible to collect everyone's public keys and put them in the server's/home/git/.ssh/authorized_keys file. If the team has a few hundred people, it won't be able to play like this. At this time, you can use Gitosis to manage the public key.

Management authority

Many companies that not only view source code as life, but also view employees as thieves, will set up a complete set of permission controls in the version control system. Whether each person has read and write permissions will be accurate to each branch or even each directory. Because Git is developed for Linux source code hosting, Git also inherits the spirit of the open source community and does not support permission control. However, because Git supports hooks, a series of scripts can be written on the server side to control submissions and other operations to achieve the purpose of permission control. Gitolite is this tool.


If you don't want to set up your own Git server, you can choose to host your Git project on an external professional hosting website. This brings some benefits: a hosting website can be used to quickly set up and start a project, without server maintenance and monitoring. Even if you set up and run in-house

8. Git internal principles

Fundamentally speaking, Git is a content-addressable file system, and on top of that it provides a user interface for a version control system.

The user interface of the early Git (mainly versions before 1.5) was much more complicated than it is now, because it was more focused on being a file system rather than a polished version control system. From time to time, there are clich s complaining about the obscure and complicated Git user interface; in recent years, it has been improved to be as clear and easy to use as any other version control system.

8.1 Low-level commands and upper-level commands

Since Git was originally a tool set for a version control system, rather than a complete and user-friendly version control system, it also contains a part of subcommands for completing the underlying work. These commands are designed to be linked together in the style of UNIX command lines, or they can be invoked by scripts to complete the work. These commands are generally referred to as "plumbing" commands , and those more friendly commands are called "porcelain" commands .

Because the low-level commands allow you to peek into the working mechanism of Git, and also help explain how Git does its work and why it works like this. Most of the low-level commands are not intended for end users: they are more suitable as components of new tools and part of custom scripts.

When you execute git init in a new directory or an existing directory, Git will create a .git directory. This directory contains almost everything Git stores and manipulates. If you want to back up or copy a version library, just copy this directory to another location.

git init default structure

$ ls -F1 config description HEAD hooks/ info/ objects/ refs/ Copy code

.Git directory that has been used for a while

COMMIT_EDITMSG//The description of the last commit FETCH_HEAD//FETCH_HEAD represents the latest state of a branch on the server. HEAD//points to the branch currently checked out ORIG_HEAD//Actually, it is also a commit. When performing some risky operations, such as reset, merge, or rebase, Git will store the sha-1 value of the commit object originally pointed to by HEAD in the ORIG_HEAD file. config//Contains project-specific configuration options. description//Only for GitWeb program use hooks///Contains client or server hook scripts (hook scripts) index//save temporary storage area information info///Contains a global exclude file to place ignored patterns that do not want to be recorded in the .gitignore file logs///Store submission logs objects///store all data content packed-refs//store the latest pointers and TAGs submitted refs///Store the pointer to the submission object of the data (branch, remote warehouse, tag, etc.) sourcetreeconfig There will be a FETCH_HEAD list for every project that has performed a fetch operation, where each row corresponds to a branch of the remote server. Copy code

The FETCH_HEAD pointed to by the current branch is the branch corresponding to the first line of this file. There are two situations: if the remote branch is not explicitly specified, the master of the remote branch will be the default FETCH_HEAD; if the remote branch is specified, the remote branch will be used as FETCH_HEAD.

Among them, the most important files are hooks/, HEAD, index, objects/, refs/

8.2 hooks (Git hooks)

Git can trigger custom scripts when certain important actions occur. There are two groups of such hooks: client-side and server-side. Client-side hooks are called by operations such as commit and merge, while server-side hooks are used for networked operations such as receiving pushed commits.

When git init initializes a new repository, Git will place some sample scripts in this directory by default. In addition to the scripts themselves can be called, they also reveal the parameters passed in when they are triggered. All the examples are shell scripts, some of which are mixed with Perl code, but any properly named executable scripts can be used normally-you can write them in Ruby or Python, or any language you are familiar with. The names of these samples all end with .sample, if you want to enable them, you have to remove this suffix first.


#!/bin/sh # # An example hook script to check the commit log message. # Called by "git commit" with one argument, the name of the file # that has the commit message. The hook should exit with non-zero # status after issuing an appropriate message if it wants to stop the # commit. The hook is allowed to edit the commit message file. # # To enable this hook, rename this file to "commit-msg". # Uncomment the below to add a Signed-off-by line to the message. # Doing this in a hook is a bad idea in general, but the prepare-commit-msg # hook is more suited to it. # # SOB=$(git var GIT_AUTHOR_IDENT | sed -n's/^\(.*>\).*$/Signed-off-by:/1/p') # grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" # This example catches duplicate Signed-off-by lines. test "" = "$(grep'^Signed-off-by: '"$1" | sort | uniq -c | sed -e'/^[ ]*1[ ]/d')" || { echo >&2 Duplicate Signed-off-by lines. exit 1 } The commit-msg hook receives a parameter, which is the path of the temporary file that contains the current commit information, as mentioned above. If the hook foot If you exit with a non-zero value, Git will abandon the submission, so it can be used to verify the status of the project or submit information before the submission is passed. Copy code

Custom commit-msg

unset GREP_OPTIONS CHANGE_ID_AFTER="Bug|Depends-On|Issue|Test|Feature|Fixes|Fixed" MSG="$1" # Check for, and add if missing, a unique Change-Id # add_ChangeId() { clean_message=`sed -e ' /^diff --git .*/{ s/// q } /^Signed-off-by:/d /^#/d '"$MSG" | git stripspace` if test -z "$clean_message" then return fi # Do not add Change-Id to temp commits if echo "$clean_message" | head -1 | grep -q'^\(fixup\|squash\)!' then return fi if test "false" = "`git config --bool --get gerrit.createChangeId`" then return fi # Does Change-Id: already exist? if so, exit (no change). if grep -i'^Change-Id:' "$MSG" >/dev/null then return fi id=`_gen_ChangeId` T="$MSG.tmp.$$" AWK=awk if [-x/usr/xpg4/bin/awk ]; then # Solaris AWK is just too broken AWK=/usr/xpg4/bin/awk fi # Get core.commentChar from git config or use default symbol commentChar=`git config --get core.commentChar` commentChar=${commentChar:-#} # How this works: #-parse the commit message as (textLine+ blankLine*)* #-assume textLine+ to be a footer until proven otherwise #-exception: the first block is not footer (as it is the title) #-read textLine+ into a variable #-then count blankLines #-once the next textLine appears, print textLine+ blankLine* as these # aren't footer #-in END, the last textLine+ block is available for footer parsing $AWK ' BEGIN { if (match(ENVIRON["OS"], "Windows")) { RS="\r?\n" # Required on recent Cygwin } # while we start with the assumption that textLine+ # is a footer, the first block is not. isFooter = 0 footerComment = 0 blankLines = 0 } # Skip lines starting with commentChar without any spaces before it. /^'"$commentChar"'/{next} # Skip the line starting with the diff command and everything after it, # up to the end of the file, assuming it is only patch data. # If more than one line before the diff was empty, strip all but one. /^diff --git/{ blankLines = 0 while (getline) {} next } # Count blank lines outside footer comments /^$/&& (footerComment == 0) { blankLines++ next } # Catch footer comment /^\[[a-zA-Z0-9-]+:/&& (isFooter == 1) { footerComment = 1 } /]$/&& (footerComment == 1) { footerComment = 2 } # We have a non-blank line after blank lines. Handle this. (blankLines> 0) { print lines for (i = 0; i <blankLines; i++) { print "" } lines = "" blankLines = 0 isFooter = 1 footerComment = 0 } # Detect that the current block is not the footer (footerComment == 0) && (!/^\[?[a-zA-Z0-9-]+:/||/^[a-zA-Z0-9-]+:\/\//) { isFooter = 0 } { # We need this information about the current last comment line if (footerComment == 2) { footerComment = 0 } if (lines != "") { lines = lines "\n"; } lines = lines $0 } # Footer handling: # If the last block is considered a footer, splice in the Change-Id at the # right place. # Look for the right place to inject Change-Id by considering # CHANGE_ID_AFTER. Keys listed in it (case insensitive) come first, # then Change-Id, then everything else (eg. Signed-off-by:). # # Otherwise just print the last block, a new line and the Change-Id as a # block of its own. END { unprinted = 1 if (isFooter == 0) { print lines "\n" lines = "" } changeIdAfter = "^(" tolower("'"$CHANGE_ID_AFTER"'") "):" numlines = split(lines, footer, "\n") for (line = 1; line <= numlines; line++) { if (unprinted && match(tolower(footer[line]), changeIdAfter) != 1) { unprinted = 0 print "Change-Id: I'"$id"'" } print footer[line] } if (unprinted) { print "Change-Id: I'"$id"'" } }'"$MSG"> "$T" && mv "$T" "$MSG" || rm -f "$T" } _gen_ChangeIdInput() { echo "tree `git write-tree`" if parent=`git rev-parse "HEAD^0" 2>/dev/null` then echo "parent $parent" fi echo "author `git var GIT_AUTHOR_IDENT`" echo "committer `git var GIT_COMMITTER_IDENT`" echo printf'%s' "$clean_message" } _gen_ChangeId() { _gen_ChangeIdInput | git hash-object -t commit --stdin } add_ChangeId Copy code

This conit-msg mainly has an add_ChangeId function, which is used to generate a changeId for this submission when committing. This changeId will be used in Gerrit's use. When Abandoned is submitted once, this changeId cannot be used. It needs to be reset locally and then resubmitted to generate a new changeId.

For change-id, please see the change-id in git commit in this article

Commit msg format automatic check actual combat

8.3 Git Object

Git is a content-addressable file system, which means that the core part of Git is a simple key-value data store. You can insert any type of content into the Git repository, and it will return a unique key, through which the content can be retrieved again at any time.

The above effect can be demonstrated through the underlying command git hash-object-this command can save any data in the .git/objects directory (ie, the object database) and return the unique key that points to the data object.

The above effect can be demonstrated through the underlying command git hash-object-this command can save any data in the .git/objects directory (ie, the object database) and return the unique key that points to the data object. 1. we need to initialize a new Git repository and confirm that the objects directory is empty:

git init test Initialized empty Git repository in/tmp/test/.git/ cd test //If you are in the window system, you can execute the command in the Git Bash Here window find .git/objects .git/objects .git/objects/info .git/objects/pack find .git/objects -type f Copy code

You can see that Git initialized the objects directory and created pack and info subdirectories, but they are all empty. Next, we use git hash-object to create a new data object and manually store it in your new Git database:

echo'projectName content' | git hash-object -w --stdin d670460b4b4aece5915caf5c68d12f560a9fe3e4 Copy code

In this simplest form, git hash-object will accept what you pass to it, and it will only return the unique key that can be stored in the Git repository. The -w option instructs the command not to just return the key, but also write the object to the database. Finally, the --stdin option instructs the command to read content from standard input; if this option is not specified, the path of the file to be stored must be given at the end of the command

git cat-file -p d670460b4b4aece5915caf5c68d12f560a9fe3e4 test content Copy code

Each version corresponds to a SHA-1 value; another problem is that in this (simple version control) system, only the content of the file is saved. We call the above-described type of the object data object (BLOB Object) .

8.3.1 Tree Object

The Git object type is a tree object, which can solve the problem of file name preservation and also allows us to organize multiple files together. Git stores content in a way similar to the UNIX file system, but with some simplification. All content is stored in the form of tree objects and data objects, where tree objects correspond to directory items in UNIX, and data objects roughly correspond to inodes or file contents. A tree object contains one or more tree entry (tree entry), each record contains a SHA-1 pointer to the data object or subtree object, and the corresponding mode, type, and file name information.

$ git cat-file -p master^{tree} 100644 blob a906cb2a4a904a152e80877d4088654daad0c859 README 100644 blob 8f94139338f9404f26296befa88755fc2598c289 Rakefile 040000 tree 99f1a6d12cb4b6f19c8655fca46c3ecf317074e0 lib Copy code

The object tree is the file corresponding to the execution of git add in the temporary storage area. The data can be multiple object trees or one object tree. You can add the object tree yourself and add the corresponding files to the object tree.

Low-level commands

//You can create a staging area for a single file the first version of the test.txt file by the low-level command git update-index. With this command, the first version of the test.txt file can be artificially added to a new temporary storage area. The --add option must be specified for the above command because the file was not in the staging area before; the --cacheinfo option is also necessary because the file to be added is located in the Git database, not in the current directory. At the same time, you need to specify the file mode, SHA-1 and file name git update-index --add --cacheinfo 100644/83baae61804e65cc73a7201a7252750c76066a30 test.txt //From the underlying command, we can see the reason why many blogs named the temporary storage area index //Write the contents of the temporary storage area into a tree object git write-tree Copy code
8.3.2 Submit object

The above object tree represents the snapshots of the items you want to track, who saved these snapshots, when they were saved, and why they were saved. The basic information saved by the commit object .

You can create a commit object by calling the commit-tree command. To do this, you need to specify the SHA-1 value of a tree object and the parent commit object of the commit (if any).

echo 'first commit' | git commit -tree d8329f duplicated code

Now you can view this new commit object through the git cat-file command:

$ git cat-file -p fdf4fc3 tree d8329fc1cc938780ffdd9f94e0d364e0ea74f579 author Scott Chacon <> 1243040974 -0700 committer Scott Chacon <> 1243040974 -0700 first commit Copy code

The format of the submission object is very simple: it first specifies a top-level tree object, which represents the current project snapshot; then the possible parent submission (the submission object described above does not have any parent submission); and then the author/submitter information (according to Set your and configuration, plus a timestamp); leave a blank line, and submit comments at the end.

Next, we will create two other submission objects, which refer to their previous submission (as their parent submission object):

$ echo'second commit' | git commit-tree 0155eb -p fdf4fc3 cac0cab538b970a37ea1e769cbbde608743bc96d $ echo'third commit' | git commit-tree 3c4e9c -p cac0cab 1a410efbd13591db07496601ebc7a059dd55cfe9 Copy code

If you track all the internal pointers, you will get an object relationship diagram similar to the following:

8.3.3 Object storage

All objects submitted to the Git repository will have a header information and be saved.

Git will first start with the recognized object type to construct a header information, then Git will add a space to the first part of the header, followed by the number of bytes of the data content, and finally a null byte, Git will Combine the above header information with the original data, and calculate the SHA-1 checksum of this new piece of content. Git will compress this new content through zlib. Finally, the content compressed by zlib needs to be written to an object on disk. Data object.

All Git objects are stored in this way, the only difference lies in the type identification-the header information of the object type starts with the string "commit" or "tree".

8.4 Citation

If we have a file to save the SHA-1 value, and the file has a simple name, and then use this name pointer to replace the original SHA-1 value, it will be easier. In Git, this simple name is called "references (or refs for short)".

Low-level command: update a reference

$ git update-ref refs/heads/master 1a410efbd13591db07496601ebc7a059dd55cfe9 Copy code

This is basically the essence of Git branches: a pointer or reference to the top of a series of commits. If you want to create a branch on the second commit, you can do this:

git update-ref refs/heads/ test cac0ca duplicated code

When running a command like git branch, Git will actually run the update-ref command to get the SHA-1 value corresponding to the latest commit of the current branch and add it to any new references you want to create.

$ find refs refs refs/.DS_Store refs/heads refs/heads/develop refs/heads/master refs/tags refs/tags/1.8.3 refs/tags/1.8.4 refs/tags/1.8.2 refs/tags/1.8.0 refs/tags/1.8.1 refs/remotes refs/remotes/.DS_Store refs/remotes/origin refs/remotes/origin/develop refs/remotes/origin/HEAD refs/remotes/origin/master refs/stash Copy code
8.4.1 HEAD reference

When you execute git branch, how does Git know the SHA-1 value of the latest commit? The answer is the HEAD file.

The HEAD file is usually a symbolic reference, pointing to the current branch. The so-called symbolic reference means that it is a pointer to other references.

When we execute git commit, the command will create a commit object and set its parent commit field with the SHA-1 value pointed to by the reference in the HEAD file.

8.4.2 Tag reference

Earlier we just discussed the three main object types of Git (data objects, tree objects, and commit objects), but there is actually a fourth type. A tag object is very similar to a submission object-it contains information about the creator of the tag, a date, a piece of comment information, and a pointer. The main difference is that the tag object usually points to a commit object, rather than a tree object. It is like a branch reference that never moves-it always points to the same commit object, but it just adds a friendlier name to the commit object.

8.4.3 Remote reference

If you add a remote repository and perform a push operation on it, Git will record the value corresponding to each branch during the last push operation and save it in the refs/remotes directory.

The main difference between remote references and branches (references located in the refs/heads directory) is that remote references are read-only. Although you can git checkout to a remote reference, Git does not point the HEAD reference to the remote reference. Therefore, you can never update the remote reference with the commit command. Git manages these remote references as bookmarks that record the state of the last known location of each branch on the remote server.

8.5 Package file

Data objects, tree objects, submitted objects, and label objects are stored in objects. The contents of some of these objects are basically similar, resulting in space occupation. The format that Git originally used to store objects on disk is called the "loose" object format. However, Git will pack multiple of these objects into a binary file called "packfile" from time to time to save space and improve efficiency. When there are too many loose objects in the repository, or you manually execute the git gc command, or you execute a push to a remote server, Git will do this.

Manual packaging:

zbt:.git zbt$ find objects -type f objects/d9/91018fc9cc614671bebb0e77310941a222c607 objects/pack/pack-8c76af529753f98845955e2a1d792d6f8dc2560a.idx objects/pack/pack-8c76af529753f98845955e2a1d792d6f8dc2560a.pack objects/81/5f3ab2a2b996a772f2dd67c078bd535f7df344 objects/info/packs zbt:.git zbt$ Copy code

After manual packaging, you will find that most of the objects are gone, and a pair of new files appear at the same time. The remaining files are the newly created package file and an index. The package file contains the contents of all the objects that were just removed from the file system. The index file contains the offset information of the package file, and we can quickly locate any specified object through the index file.

After gc, the object file size has been reduced by a lot of M

8.6 Reference Standard

Link local warehouse and remote warehouse

git remote add origin wegene- mobile-dev/wegene_android.git duplicated code

Run the above command will add .git/config file in your repository in a section, in which you specify the name of the remote repository (origin), URL and operations used to obtain a reference specification (refspec) :

[remote "origin"] url = fetch = +refs/heads/*:refs/remotes/origi Copy code

The format of the reference specification consists of an optional + sign followed by:, where is a pattern, which represents the reference in the remote version library; it is the location of the remote reference that is tracked locally. The + sign tells Git to (force) update the reference even if it cannot fast forward.

By default, the reference specification is automatically generated by the git remote add origin command. Git gets all references under refs/heads/in the server and writes them to the local refs/remotes/origin/. Therefore, if there is a master branch on the server, you can access the commit records on that branch locally through any of the following methods.

8.7 Transmission Protocol

Git can transfer data between repositories in two main ways: the "dumb" protocol and the "smart" protocol.

8.7.1 Dumb protocol

If you are setting up a read-only repository based on the HTTP protocol, generally speaking, the dumb protocol is used in this case. The reason why this protocol is called "dumb" protocol is because in the transmission process, the server does not need to have Git-specific code; the crawling process is a series of HTTP GET requests, in this case, the client can infer The layout of the server-side Git repository.

8.7.2 Smart Agreement

Although the dumb protocol is very simple, it is slightly inefficient, and it cannot send data from the client to the server. The smart protocol is a more commonly used method of transferring data, but it requires a process to run on the server side, and this is also the intelligence of Git-it can read local data, understand what the client has and what it needs, and provide it for it Generate the appropriate package file. There are two sets of processes used to transfer data, and they are responsible for uploading and downloading data.

upload data

In order to upload data to the remote end, Git uses send-pack and receive-pack processes. The send-pack process running on the client is connected to the receive-pack process running on the remote end.

git push origin master copy the code

Because origin is defined based on the URL of the SSH protocol. Git will run the send-pick process, which attempts to connect to the server and executes a command on the server side via SSH, as follows:

$ ssh -x git@server "git-receive-pack'simplegit-progit.git'" 00a5ca82a6dff817ec66f4437202690a93763949 refs/heads/master report-status/ delete-refs side-band-64k quiet ofs-delta/ agent=git/2:2.1.1+github-607-gfba4028 delete-refs 0000 Copy code

The git-receive-pack command will immediately send a line of response for each reference it owns-in this example, only the master branch and its SHA-1 value.

The first line of the response also contains a list of server capabilities (here are report-status, deleterefs, and some others, including the client's identification code).

Each line starts with a four-digit hexadecimal value to indicate the length of the line. You see that the first line starts with 00a5, which means 165 in hexadecimal, which means that the first line has 165 bytes. The next line is 0000, indicating that the server has completed the process of sending the reference list.

Now that it knows the status of the server, your send-pack process will determine which commit records it owns but the server does not. sendpack will inform receive-pack of the references (references in the previous section) that will be updated by this push. For example, if you are updating the master branch and adding the experiment branch, the send-pack response will be like this:

0076ca82a6dff817ec66f44342007202690a93763949 15027957951b64cf874c3557a0f3547bd83b3ff6/ refs/heads/master report-status 006c0000000000000000000000000000000000000000 cdfdb42577e2506715f8cfeacdbabc092bf63e8d/ refs/heads/experiment 0000 Copy code

The first line also includes the capabilities of the client. The SHA-1 value of all 0s here means that there has not been this reference before because you are about to add a new experiment reference. When you delete the reference, you will see the opposite: the SHA-1 values on the right are all 0s.

The connection starts with the following request:

=> GET http://server/simplegit-progit.git/info/refs?service=git-receivepack 001f# service=git-receive-pack 00ab6c5f0e45abd7832bf23074a333f739977c9e8188 refs/heads/master reportstatus \ delete-refs side-band-64k quiet ofs-delta/ agent=git/2:2.1.1~vmg-bitmaps-bugaloo-608-g116744e 0000 Copy code

This completes the first data exchange between the client and the server. Next, the client initiates another request, this time a POST request, which contains the data provided by send-pack.

=> POST http://server/simplegit-progit.git/git-receive-pack copy the code

The content of this POST request is the output of send-pack and the corresponding package file. After receiving the request, the server responds with a successful or failed HTTP response accordingly.

Download data

When you are downloading data, the fetch-pack and upload-pack processes come into play. The client starts the fetch-pack process and connects to the remote upload-pack process to negotiate subsequent data transmission.

If you use the fetch function via SSH, fetch-pack will run like this:

$ ssh -x git@server "git-upload-pack'simplegit-progit.git'"

After fetch-pack is connected, upload-pack will return something similar to the following:

00dfca82a6dff817ec66f44342007202690a93763949 HEAD multi_ack thin-pack/ side-band side-band-64k ofs-delta shallow no-progress include-tag/ multi_ack_detailed symref=HEAD:refs/heads/master/ agent=git/2:2.1.1+github-607-gfba4028 003fe2409a098dc3e53539a9028a94b6224db9d6a6b6 refs/heads/master 0000 Copy code

This is very similar to the receive-pack response, but the capabilities included here are different. And it also contains the content pointed to by the HEAD reference (symref=HEAD:refs/heads/master) so that if the client is performing a clone, it will know what to check out.

At this time, the fetch-pack process looks at the objects it owns and responds with the SHA-1 value of "want" and the objects it needs. It also sends "have" and the SHA-1 values of all objects it already owns. At the end of the list, it will also send "done" to notify the upload-pack process that it can start sending the package files of the objects it needs.

The handshake of the fetch operation requires two HTTP requests. The first is to send a GET request to the same endpoint as in the dumb protocol.

This is very similar to using git-upload-pack via SSH, but the second data exchange is a separate request.

8.8 Maintenance and data recovery

Clean data, update data, and restore data

8.8.1 Maintenance

Git will automatically run a command called "auto gc" from time to time. Most of the time, this command has no effect. However, if there are too many loose objects (objects not in the package file) or too many package files, Git will run a full git gc command. "Gc" stands for garbage collection. This command will do the following: collect all loose objects and place them in the package file, merge multiple package files into one big package file, and remove obsolete files that are not related to any submission Object.

You can manually perform automatic garbage collection as follows:

$ Git gc --auto copy the code

As mentioned above, this command usually has no effect. It takes about 7000 loose objects or more than 50 package files for Git to start a real gc command. You can modify these values by modifying the settings of and gc.autopacklimit.

8.8.2 Data Recovery

For example, after a certain commit, we use git reset to reset the branch to a certain commit, then some of the commits in the middle will disappear. How to recover in this situation? At this time, you can use the git reflog tool.

When you are working, Git will silently record the value of HEAD every time you change it. Every time you commit or change a branch, the reference log will be updated. The reflog can also be updated through the git update-ref command.

9d9451c (HEAD -> dev) HEAD@{0}: reset: moving to 9d9451 bc48bd6 HEAD@{1}: reset: moving to HEAD bc48bd6 HEAD@{2}: reset: moving to HEAD bc48bd6 HEAD@{3}: commit: reset test 2 9d9451c (HEAD -> dev) HEAD@{4}: reset: moving to 9d9451c4b0243c7423d44449d7150c9444f17967 842faa0 HEAD@{5}: reset: moving to 842faa0ee8c366b53164241defcd967ac9d7d618 842faa0 HEAD@{6}: reset: moving to 842faa0ee8c366b53164241defcd967ac9d7d618 842faa0 HEAD@{7}: reset: moving to HEAD Copy code

This can be updated according to the sha1 value

8.8.3 Remove objects

For example, if you submit a large file and need to delete it, then it will rewrite every submission from the time you have to modify or remove a large file that references the earliest tree object. If after you import the repository, anyone starts to perform this operation based on these submissions, then there will be no problems-otherwise, you must notify all contributors that they need to rebase their results to your new submission on.

8.9 Environment variables

Git always runs in a bash shell, and uses some shell environment variables to determine how it runs. Sometimes it is useful to know what they are and how they make Git run the way you want. Not all Git environment variables will be listed here, but we will cover the most useful part.

8.9.1 Global Behavior

It is to configure environment variables. Like normal programs, Git's normal behavior depends on environment variables.

GIT_EXEC_PATH determines where Git will find its subprograms (like git-commit, git-diff, etc.). You can use git --exec-path to view the current settings. '

Usually you don't consider modifying the HOME variable (too many other things rely on it), this is where Git looks for global configuration files. If you want a truly portable version of Git that includes global configuration, you can override the HOME setting in the shell configuration of the portable version of Git.

PREFIX is similar, except for system-level configuration. Git looks for this file in $PREFIX/etc/gitconfig.

If GIT_CONFIG_NOSYSTEM is set, the system-level configuration file is disabled. This is useful when the system configuration affects your commands and you don't have permission to modify them.

GIT_PAGER controls the program that displays multiple pages of output on the command line. If this is not set, PAGER will be used.

GIT_EDITOR When the user needs to edit some text (such as submission information), Git will start this editor. If it is not set, EDITOR will be used.

8.9.2 Repository location

Git uses several variables to determine how it interacts with the current repository.

GIT_DIR is the location of the .git directory. If this is not set, Git will look up the .git directory layer by layer according to the directory tree until it reaches ~ or/.

GIT_CEILING_DIRECTORIES controls the behavior of finding .git directories. If you access a slow loading directory (such as those on a tape drive or through a network connection), you may want Git to stop trying early, especially if Git is called during the shell build.

GIT_WORK_TREE is the root path of the working directory of the non-empty repository. If --git-dir or GIT_DIR is specified but --work-tree, GIT_WORK_TREE or core.worktree is not specified, then the current working directory will be regarded as the top-level directory of the working tree.

GIT_INDEX_FILE is the path of the index file (only available in non-empty repositories).

GIT_OBJECT_DIRECTORY is used to specify the location of the .git/objects directory.

GIT_ALTERNATE_OBJECT_DIRECTORIES A colon-separated list (similar to/dir/one:/dir/two: ) is used to tell Git where to find objects that are not in the GIT_OBJECT_DIRECTORY directory.

If you have many projects with large files with the same content, this can be used to avoid storing too many backups.

8.9.3 Path Rules

The so-called "pathspec" refers to how you specify the path in Git, including the use of wildcards. They will be used in the .gitignore file and also in the command line (git add *.c).

8.9.4 Submit

The creation of Git commit objects is usually finally done by git-commit-tree, and git-commit-tree uses these environment variables as the main source of information. Only when these values do not exist will it fall back to the preset value.

8.9.5 Network

Git uses the curl library to complete network operations over HTTP, so GIT_CURL_VERBOSE tells Git to display all messages generated by that library. This is similar to executing curl -v on the command line.

8.9.6 Compare and merge
8.9.7 Debug

GIT_DIFF_OPTS is a wrong name. Valid values only support -u or --unified=, which are used to control the number of content lines displayed in the git diff command.

GIT_EXTERNAL_DIFF is used to override the value configured in diff.external. If this value is set, Git will call the program when git diff is executed.

GIT_DIFF_PATH_COUNTER and GIT_DIFF_PATH_TOTAL are useful for programs specified by GIT_EXTERNAL_DIFF or diff.external. The former indicates which file is compared in a series (starting from 1), and the latter indicates the total number of files in each batch.

GIT_MERGE_VERBOSITY controls the output of the recursive merge strategy. The allowed values are the following:

0. Nothing is output, except there may be an error message. 1. Only show conflicts. 2. The file changes are also displayed. 3. Display the files that were skipped because they were not changed. 4. Display all paths processed. 5. Display detailed debugging information. Copy code

The default value is 2. debugging

8.9.8 Other

If GIT_SSH is specified, Git will replace ssh with the specified program when connecting to the SSH host. It will be called by the command mode of $GIT_SSH[username@]host [-p ]. This is not the easiest way to configure a custom ssh invocation method; it does not support additional command line parameters, so you must write a wrapper script and let GIT_SSH point to it. It might be easier to use ~/.ssh/config.

9 git command

9.1 Installation configuration commands
#sudo apt-get install git #sudo apt-get install git-doc git-svn git-email git-gui gitk Initialize git ssh-keygen #Generate git key by default in the .ssh directory git init # Create a new Git code repository in the current directory git init [project-name] # Create a new directory and initialize it as a Git code base git clone [url]# Download a project and its entire code history git config --list# Display the current Git configuration git config -e [--global]# Edit Git configuration file # Set the user information when submitting the code git config --global "" git config --global "Your Name" Copy code
9.2 Code submission related commands
git clone name.git # download code from remote warehouse git status. # View the modification of the current workspace git add * # track new files git add -A commit all changes git add -u Submit modified and deleted files, excluding new files (new) git add. Submit new files (new) and modified (modified) files, excluding deleted (deleted) files rm *&git rm * # remove files git rm -f * # remove files git rm --cached * # Stop tracking the specified file, but the file will remain in the workspace git mv file_from file_to # Rename the tracking file git log # View submission records git commit # Submit update git commit [file1] [file2] ... # Submit the specified file git commit -m'message' git commit -a # Skip using the temporary storage area, temporarily store all tracked files and submit them together git commit --amend#Modify the last commit git commit -v # Display all diff information when submitting git reset HEAD *#Cancel a file that has been temporarily stored git reset --mixed HEAD *# Same as above git reset --soft HEAD *#Reset to the specified state without modifying the index area and working tree git reset --hard HEAD *#Reset to the specified state, will modify the index area and working tree git reset - files#Reset index area files git revert HEAD #Undo the previous operation git revert HEAD~ #Undo the previous operation git revert commit ## Cancel the specified operation git checkout - file#Cancel the modification of the file (from the temporary storage area-overwrite the worktree file) git checkout branch|tag|commit - file_name#Remove the file from the warehouse to cover the current branch git checkout - .#Remove files from the temporary storage area to cover the work area git diff file #View the difference of the specified file git diff --stat #View simple diff results git diff #Compare the difference between Worktree and Index git diff --cached #Compare the difference between Index and HEAD git diff HEAD #Compare the difference between Worktree and HEAD git diff branch #Compare the difference between Worktree and branch git diff branch1 branch2 #Compare the difference between the two branches git diff commit commit #Compare the difference between two submissions git log --grep=aplog #Find keywords aplog git log #View the recent commit log git log --pretty=oneline #single line display commit log git log --graph # Graphical display git log --abbrev-commit # Display the abbreviation of log id git log -num #Display the first log (countdown) git log --stat # Display the commit history and the files that have changed each time the commit git log --follow [file] # Display the version history of a file, including file renaming git log -p [file] # Display every diff related to the specified file git log --oneline #Only one line shows that each submission contains the hash number and commit content git stash #Store the work area (tracked files) and continue working after recovery. git stash list #View the saved work site git stash apply #Restore the work site git stash drop #Delete stash content git stash pop #Delete stash content directly while restoring. It is best not to do this unless you confirm that you will not use cached data again git stash apply stash@{0} #Restore the specified job site, when you save more than one job site. Copy code
9.3 Branch operation command

Note: #XXX is the explanation of the command, do not carry it when using the command

git branch #List local branches git branch -r #List remote branches for easy viewing, there will be an * in front of them. git branch -a #list all branches git branch -v #View the information of the last commit object of each branch git branch --merge #View the branches that have been merged into the current branch git branch --no-merge #View the branch that is merged into the current branch git branch test #New test branch git branch branch [branch|commit|tag] # Create a new branch from the specified location git branch --track branch remote-branch # Create a new branch and establish a tracking relationship with the specified remote branch git branch -m old new #Rename branch git branch -d test #Delete the test branch git branch -D test #Forced deletion of test branch can delete multiple branches at the same time git branch --set-upstream dev origin/dev #Establish a link between the local dev branch and the remote dev branch git checkout test #Switch to the test branch git checkout -b test #New + switch to test branch git checkout -b test dev #Create a new test branch based on dev and switch git merge test #Merge the test branch to the current branch git merge --squash test ## Merge and compress, compress the commit on test into one git cherry-pick commit #Select the merge and merge the commit to the current branch. For example, we made a modification under the dev branch before and then switched to the master to synchronize the latest code. You can submit the previous commit through cherry-pick Sync over git cherry-pick -n commit #Select multiple submissions, after merging, you can continue to select the next submission git rebase master #divide the master into advanced submissions and rebase to the current branch git rebase --onto master 169a6 #Limit the scope of rollback, rebase the current branch from 169a6 and later submissions git rebase --interactive #Interactive mode git rebase --continue #Continue to merge after dealing with conflicts git rebase --skip #skip git rebase --abort #Cancel merge Copy code
9.4 Remote branch related commands
git fetch origin remotebranch[:localbranch] # Pull the branch from the remote [to the local designated branch] git merge origin/branch #Merge the specified branch on the remote git pull origin remotebranch:localbranch # Pull the remote branch to the local branch git push origin branch #Push the current branch to the specified branch on the remote git push origin localbranch:remotebranch #Push the local designated branch to the designated branch on the remote git push origin :remotebranch #Delete the remote designated branch git push origin remotebranch --delete #Delete remote branch git branch -dr branch #Delete local and remote branches git checkout -b [--track] test origin/dev #Based on the remote dev branch, create a new local test branch [set tracking at the same time] Copy code
9.5 Other commands
//remote library git remote add origin1 #Add source git remote #show all sources git remote -v #Display all sources + detailed information git remote rename origin1 origin2 #renaming git remote rm origin #delete git remote show origin #View all information of the specified source //Commands to avoid as much as possible git push -f origin master //Synchronize the Cultural Revolution files of other branches //Sync the resource_tool under the yan3_dev branch to the current branch git show yan3_dev:scripts/resource_tool>scripts/resource_tool //Package project source command related git clone --bare kernel/#This will generate kernel.git This will contain the .git folder git clone kernel.git/#Unpack like this //Patch command git diff ./> *.patch patch -p1 //View historical branches git log graph all //Use prompt or help git help commit Copy code


git official documentation

git tutorial

Tencent Cloud Git Tutorial

Essay Classification-git