Git practical skills record, read this article and you will understand!

"Only when you encounter problems can you realize the benefits of skills!

If we want to quickly understand or experience Git's operation, I recommend going to this website for learning. It does not require us to install tools, and we can see the status of each step of our operation in real time on the right, which is very helpful for us to learn and understand Git's working mode and principle. - Welcome = > https://oschina.gitee. io/learn-Git-branching/

Common enterprise workflow

It mainly introduces the Git workflow commonly used in enterprises!

Git Flow:

  • main branch
  • Stable branch
  • Development Branch
  • Patch branch
  • Modify branch

GitHub Flow:

  • Create branch
  • Add submit
  • Submit PR request
  • Discuss and evaluate code
  • Deployment detection
  • Merge code

GitLab Flow:

  • With production branch
  • Branch with environment
  • With publishing branch

Best practices for daily use

Summarize the Git usage and methods that should be followed in daily work!

Use the command line instead of the graphical interface:

  • Use the command line to operate, simple and efficient

The submitter shall state the contents of the submitted amendment as much as possible:

  • Distinguish between subject and body contents and separate them with blank lines
  • subject generally does not exceed 50 characters
  • The length of each line of body is controlled to 72 characters
  • subject does not need to end with a period or a period
  • body is used to explain in detail what the submission has done

Use the. gitignore file to exclude unwanted files:

  • You can use the template file and modify it according to the actual situation of the project

Branch or fork based development mode:

  • Do not develop directly on the trunk branch
  • Develop functions and repair problems on the new branch

Use the release branch and tag tag for version management:

  • Release code and version maintenance using the release branch (release/1.32)
  • Use tag to mark the version (A - large feature function; B - small feature function; C - fix bug s only)

Summary of common commands

Just remember 6 commands for daily use.

# Workspace - > staging area
$ git add <file/dir>

# Staging area - > local warehouse
$ git commit -m "some info"

# Local warehouse - > remote warehouse
$ git push origin master  # The local master branch is pushed to the remote origin warehouse
# Workspace < - staging area
$ git checkout -- <file>  # The contents of the staging area file overwrite the contents of the workspace file

# Staging area < - local warehouse
$ git reset HEAD <file>   # The contents of the local warehouse file overwrite the contents of the staging area file

# Local warehouse < - Remote warehouse
$ git clone <git_url>        # Clone remote warehouse
$ git fetch upstream master  # Pull remote code to local but not applied to current branch
$ git pull upstream master   # Pull remote code to local but apply in current branch
$ git pull --rebase upstream master  # If you normally use rebase to merge codes, add
# Workspace < - local warehouse
$ git reset <commit>          # Overwrite the local warehouse to the work area (save and modify the contents of the fallback file)
$ git reset --mixed <commit>  # Overwrite the local warehouse to the work area (save and modify the contents of the fallback file)
$ git reset --soft <commit>   # Overwrite the local warehouse to the workspace (keep the modification and add it to the staging area)
$ git reset --hard <commit>   # Overwrite the local warehouse to the work area (delete it directly without reservation)

Configure utility parameter options

Although the configuration is relatively simple, it is very useful!

Global configuration

# User information
$ git config --global "your_name"
$ git config --global "your_email"

# text editor
$ git config --global core.editor "nvim"

# Pager
$ git config --global core.pager "more"

# alias
$ git config --global "git status"

# error correction
$ git config --global help.autocorrect 1

Personal configuration

# If the -- global parameter is not added, it is a personal configuration
$ git config --list
$ git config
$ git config "your_name"

# If it is set in the project, it is saved in the. git/config file
$ cat .git/config
    name = "your_name"

Selection of merge and variable base

When to use merge and rebase?

Search the official account, the back architect answers the monkey, and gets a surprise package.

Use merge operation - the Requests Library in Python is in use

Developers who support the use of merge believe that the submission history of the warehouse is to record what actually happened. It is a document for history. In fact, it is valuable and should not be modified at will. If we change the history, it is equivalent to using "lies" To cover up what actually happened, and these traces should be retained. Maybe, this is not very good.

# The commit of the two branches of the 3rd modifies the same content
*   62a322d - (HEAD->master) Merge branch 'hotfix3' into master
| * 6fa8f4a - (hotfix3) 3rd commit in hotfix3
* | 548d681 - 3rd commit in master
* 6ba4a08 - 2nd commit
* 22afcc1 - 1st commit

Use rebase operation - the Django Library in Python is in use

Developers who support rebase think that the submission history is something that happened during the project, and the trunk of the project needs to be very clean. Using merge operation will generate a merge commit object, which will add some very redundant content to the submission history.

When we use the log command to refer to the submission history later, we will find that the submission history of the trunk is very embarrassing. For example, the same modification is submitted twice, which is obviously caused by branch merging.

# The commit of the two branches of the 3rd modifies the same content
* 697167e - (HEAD -> master, hotfix) 3rd commit
* 6ba4a08 - 2nd commit (2 minutes ago)
* 22afcc1 - 1st commit (3 minutes ago)

Use principle of both

The general principle is to clean up the history only for local modifications that have not been pushed or shared with others, and never for the submitted records that have been pushed to the warehouse. In this way, you can enjoy the convenience brought by the two methods.

Update warehouse submission history

Git provides some tools to help us improve the submitted content in the version library, such as:

Merge multiple commit commit records

In daily development, we submit many commit records in order to complete a function or feature. However, in the end, we should sort out these commit records before submitting PR. some commit records need to be merged or deleted, etc.

# Adjust the last five submission records
$ git rebase -i HEAD~5
$ git rebase -i 5af4zd35  # commit value for the sixth time
reword c2aeb6e 3rd commit
squash 25a3122 4th commit
pick 5d36f1d 5th commit
fixup bd5d32f 6th commit
drop 581e96d 7th commit

# View submission history
$ git log
* ce813eb - (HEAD -> master) 5th commit
* aa2f043 - 3rd commit -> modified
* 6c5418f - 2nd commit
* c8f7dea - 1st commit


List of options

Interpretation of corresponding meaning



Use this commit record



Use this commit record; and modify the submission information



Use this commit record; rebase will pause and allow you to modify this commit



Use this commit record; the current commit will be merged with the previous commit



The same as the squash option; however, the submission information of the current commit will not be saved



Execute other shell commands



Remove this commit record

Delete unexpected debug test code

Sometimes after submitting, we find these problems in the submitted history. At this time, we don't want to generate a new commit record and reach a modified directory, that is, modify the previous commit record.

# Do not use pager
$ git --no-pager log --oneline -1
d5e96d9 (HEAD -> master) say file

# Change the submission information and add it to the staging area
$ echo "hello" > say.txt
$ git add -u

# Change the current latest submission record
$ git commit --amend
# Changed and unchanged submission letter
$ git commit --amend --no-edit
# Change the current latest submission record and modify the information
$ git commit --amend -m "some_info"

# Do not use pager
$ git --no-pager log --oneline -1
9e1e0eb (HEAD -> master) say file

Cancel partial commit in multiple commits

We have developed a function. When we went online, the product manager said that some features of this function are no longer needed, that is, the submission records and contents of relevant features can be ignored / deleted.

# Rollback operation (rollback operation can be performed multiple times)
# Complete the last submission record; it can also be the submission record of PR
# A new commit object of type reverts is generated by default
$ git revert 3zj5sldl

Merge certain commit submissions

We don't want to merge the whole branch, but we need to merge some submission records of the branch.

# Cherry picking
$ git cherry-pick -x z562e23d

Use reference logging

How to retrieve our lost content and records?

As we said before, using the following commands to rollback content, force push code, and delete local branches are very dangerous operations, because we can't find the previous modified content after reset.

# Back off
$ git reset --hard <commit>

# Push
$ git push origin master -f

# branch
$ git branch -D <branch_name>

In fact, Git left us a back door, which is to use the relflog command to retrieve the previous content, but it is relatively troublesome. The principle is also very simple. When we use Git command to operate the warehouse, Git secretly helps us record all operations.

# View log records
$ git --no-pager log --oneline -1
4bc8703 (HEAD -> master) hhhh

# Fallback to last submission
$ git reset --hard HEAD~1

# View reference log records
$ git reflog
6a89f1b (HEAD -> master) HEAD@{0}: reset: moving to HEAD~1
4bc8703 HEAD@{1}: commit (amend): hhhh

# Retrieve content
$ git cherry-pick 4bc8703

Batch modification history submission

Although batch modification history submission is not commonly used, it can save a lot of time if you understand it!

The commands we learned before are all for modifying one or more commit submission information. What if we need to modify the historical submission globally? Of course, Git also supports global modification history submission, such as global modification of mailbox address, or deletion or modification of a file from global history.

  • The open source project uses the company mailbox for submission
  • The submission contains information about the password for privacy
  • When submitting, the large file is submitted to the warehouse code

Here, we can use the filter brace method to modify, but it is recommended to create a new branch before use, test it on it, and then operate on the trunk to prevent problems and carry a big pot on the body.

# Create branch
$ git branch -b testing

# Modify email address
$ git filter-branch --commit-filter '
    if [ "$GIT_AUTHOR_EMAIL" == "" ]; then
        git commit-tree "$@"
        git commit-tree "$@"
    fi' HEAD

Flexible use of hook functions

Mainly introduces the sample hook function under the. git/hooks directory!

There are two types in Git, corresponding to client and server hook functions respectively. The client-side hook function is called when performing operations such as submit and merge. The server hook function is the step of code checking and continuous integration after the server receives the code submission. As a developer, we don't build Git server, so we won't involve it.

The following is Git's built-in hook script, but the built-in. sample is used as the suffix, indicating that it is not enabled. It is shown as an example. If it needs to be enabled, delete. sample as the suffix. The corresponding content of the hook script is written using Shell syntax.

➜ ll .git/hooks
total 112
-rwxr-xr-x  applypatch-msg.sample
-rwxr-xr-x  commit-msg.sample
-rwxr-xr-x  fsmonitor-watchman.sample
-rwxr-xr-x  post-update.sample
-rwxr-xr-x  pre-applypatch.sample
-rwxr-xr-x  pre-commit.sample
-rwxr-xr-x  pre-merge-commit.sample
-rwxr-xr-x  pre-push.sample  # commit submissions containing WIP will not be pushed
-rwxr-xr-x  pre-rebase.sample
-rwxr-xr-x  pre-receive.sample
-rwxr-xr-x  prepare-commit-msg.sample
-rwxr-xr-x  update.sample

In fact, hook scripts can be written in any language, as long as you let the program return the corresponding exit code.

The normal code integration process is that after local modification, we make a PR request and pass the CI check of Github, then conduct code review, and finally merge it into the trunk. However, a good habit is to ensure that there are no basic problems such as syntax errors before code submission, such as passing flake8 and PEP8 standards.

At this time, we can use pre commit [1], an open source project of GitHub. Its essence is to add a script of hook function to the project, which can ensure that we check the quality of the code before submitting or pushing the code.

The pre commit hooks [2] project contains the currently supported hook scripts, that is, the set of hook scripts out of the box. The corresponding content of the hook script is written using Python syntax.

# Installation mode
$ pip install pre-commit

# Specify the hook type (i.e. where to check)
$ pre-commit install -f --hook-type pre-push

# Configure the checks that need to be performed
$ cat .pre-commit-config.yaml
- repo:
  rev: v2.9.2
    - id: trailing-whitespace
    - id: flake8

# Check when push ing
$ git push origin master

Rapid cloning of large projects

In large projects, pulling code takes up a lot of time!

If we want to contribute to a large project such as Linux or Python, the first problem we encounter when submitting is to quickly clone the project locally. Because there are too many submission histories and huge warehouses for the project, plus the problem of domestic network, our enthusiasm may be reduced when the project is completely pulled down.

Fortunately, GIT also helps us think of such a problem. We can use the -- depth parameter value to pull the latest submission history on the remote warehouse, which does not include the project history, that is, the objects in the. git/objects / directory are only local and do not include the objects generated by previous modifications.

# Clone does not contain previous history
$ git clone --depth=1

However, sometimes we may need the content corresponding to a tag version in the clone warehouse. If we cannot use the clone command directly, we need to perform the following operations to solve it perfectly.

# Clone specific version code
$ git init xxx-15-0-1
$ git remote add origin
$ git -c protocol.version=2 fetch origin 15.0.1 --depth=1
$ git checkout FETCH_HEAD

The above effect can basically meet our daily use needs, but unfortunately, you have accepted a machine learning project, which contains a large number of lfs files, and now clone will become very slow. The following operations can be used to avoid. Git tool actively pulls the lfs file to reach the directory.

# The clone does not contain LFS data
$ GIT_LFS_SKIP_SMUDGE=1 git clone

How to deal with work interruption

If in multi-channel operation, it can also be developed efficiently!

For example, we are now adding a small function to the project in a branch. At this time, the product manager finds you and says that there is a bug in the online environment that needs to be fixed by you. However, the small functions we added are not completed at this time.

If we switch directly to the trunk branch at this time, we will bring all the contents that the branch did not have time to submit to the trunk branch. This is what we don't want to see. At this point, we need to save the working state of the last branch and continue working after we modify the online bug.

Fortunately, Git also helps us think of such a problem. We can use the stash subcommand to help us save the changes in the current workspace and staging area to the stack. When it needs to be processed, the contents in the stack will pop up, and we will develop again.

➜ git stash -h
usage: git stash list [<options>]
   or: git stash show [<options>] [<stash>]
   or: git stash drop [-q|--quiet] [<stash>]
   or: git stash ( pop | apply ) [--index] [-q|--quiet] [<stash>]
   or: git stash branch <branchname> [<stash>]
   or: git stash clear
   or: git stash [push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]
          [-u|--include-untracked] [-a|--all] [-m|--message <message>]
          [--pathspec-from-file=<file> [--pathspec-file-nul]]
          [--] [<pathspec>...]]
   or: git stash save [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]
          [-u|--include-untracked] [-a|--all] [<message>]
# Store the current changes without commit ting
$ git stash

# Save the current state, including untracked files
$ git stash -u

# Show all stashes information
$ git stash list

# Return to a stash state
$ git stash apply <stash@{n}>

# Delete storage area
$ git stash drop <stash@{n}>

# Return to the state of the last stash and delete the stash information
$ git stash pop

# Delete all stash information
$ git stash clear

# Take out the modification of a file from the stash
$ git checkout <stash@{n}> -- <file-path>

In fact, the safer way is to push all the current changes and save them to the remote warehouse. The advantage of this is that we can back up our changes remotely without fear of local file loss and other problems. When we need to continue development, pull down the corresponding content and find ways to remedy it, such as using -- amend or reset command.

# Overwrite the workspace and staging area with the most recent submission
$ git commit --amend
$ git commit --amend -m "some_info"

# Fallback to the specified version and record the changes (- - mixed)
# Overwrite the local warehouse to the work area (save and modify the contents of the fallback file)
$ git reset a87f328
$ git reset HEAD~
$ git reset HEAD~2
$ git reset <tag>~2
$ git reset --mixed <commit/reference>

# Overwrite the local warehouse to the work area (delete it directly without reservation)
$ git reset --soft <commit/reference>
# Overwrite the local warehouse to the workspace (keep the modification and add it to the staging area)
$ git reset --hard <commit/reference>

Related links:


IT technology sharing community

Personal blog website:

Posted on Fri, 12 Nov 2021 04:16:12 -0500 by penguinboy