Official account: Java Xiaokaxiu, website: Javaxks.com

Author: the Escape links: www.escapelife.site/posts/f6ffe…

It is only when you encounter problems that you realize the benefits of skill!

Common enterprise workflow

Git workflow is commonly used in the enterprise.

Git Flow

  • The trunk
  • Stable branch
  • Development branch
  • Patch branch
  • Modify the branch

Github Flow

  • Create a branch
  • Add to submit
  • Submit a PR request
  • Discuss and evaluate the code
  • Deployment of detection
  • Merge code

Gitlab Flow

  • Belt production branch
  • Band environment branch
  • Branch with publication

Best practices for daily use

Summary of the daily work should follow the use of Git and methods!

  • Use the command line instead of a graphical interface

    • Using the command line is simple and efficient
  • The commit should be as descriptive as possible about the commit changes

    • Separate subject and body content using a blank line
    • Subject usually contains no more than 50 characters
    • Each line of the body should be 72 characters long
    • The end of subject does not need to end with a period or a dot
    • The body is used to explain in detail what this submission does
  • Use the.gitignore file to eliminate useless files

    • You can use template files and then modify them based on your project
  • Branch – or fork-based development patterns

    • Do not develop directly on the trunk branch
    • Develop functionality and fix problems on the new branch
  • Use the Release branch and tag tags for version management

    • Release code and version maintenance using the Release branch (Release /1.32)
    • Use A tag to mark the version (a-large feature feature). B – Small feature function. C – Fix bugs only)

Common commands are summarized

Just remember six commands for everyday use.

$git commit -m "some info"# git push origin master # $git reset HEAD <file> # $git clone <git_url> $git fetch upstream master $git pull --rebase upstream master $git pull --rebase upstream master $git reset --mixed <commit> # $git reset --soft <commit> $git reset --hard <commit>Copy the code

Configure utility parameter options

The configuration is simple, but very useful!

Global configuration

$git config --global user.name "your_name" $git config --global user.email "your_email --global core.editor "nvim" # pager $git config --global core.pager "more" # alias $git config --global alias.gs "git $git config --global help. Autocorrect 1Copy the code

Personal configuration

$git config --list $git config user.name $git config user.name "your_name" $cat. git/config [user] name = "your_name"......Copy the code

Merge and rebase options

When do you merge and when do you rebase?

Use the merge operation – used by the Requests library in Python

Developers who support merge argue that the commit history of the repository is a record of what actually happened, that it is a historical document that is valuable in its own right and should not be modified at will. When we change history, we use “lies” to cover up what actually happened, and these traces should be preserved. Maybe that’s not so good.

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

Use the rebase operation – used by the Django library in Python

Support developers using Rebase, who believe that the commit history is something that happens during the project and needs the backbone of the project to be very clean. Merge generates a MERGE COMMIT object, making the commit history a bit redundant.

When we look at the commit history using the log command later, we will find that the commit history of the trunk is very embarrassing. For example, the same change is committed twice, which is clearly a branch merge problem.

* 697167e - (HEAD -> master, hotfix) 3rd commit * 6ba4a08 - 2nd commit (2 minutes ago) * 22afcc1 - 1st commit (3 minutes ago)Copy the code

Principle of use of both

As a general rule, only base clean history on local changes that haven’t been pushed or shared with others, and never base commit records that have been pushed to the repository, so you can get the benefit of both approaches.

Update the warehouse commit history

Git provides a number of tools to help you improve your repository commits, such as:

Merge multiple COMMIT records

In daily development, we commit multiple commit records to complete a feature or feature. But at the end of the day, before submitting the PR, it’s normal to sort out the submission records. Some commits need to be merged, deleted, and so on.

$git rebase -i HEAD~5 $git rebase -I 5af4zd35 reword c2AEb6e 3rd commit squash 25a3122 4th commit pick 5d36f1D 5th commit fixup bd5d32f 6th commit drop 581e96d 7th commit # check the commit history $git log * ce813eb - (HEAD -> master) 5th commit * aa2f043 - 3rd commit -> modified * 6c5418f - 2nd commit * c8f7dea - 1st commitCopy the code

Remove test code that was accidentally debugged

Sometimes, after a commit, we realize that there are problems in the commit history, and we don’t want to generate a new COMMIT record and reach a modified directory. That is, modify the previous COMMIT record.

$git --no-pager log --oneline -1 d5e96d9 (HEAD -> master) say file $git --no-pager log --oneline -1 d5e96d9 (HEAD -> master) say file Git add -u $git commit $git commit --amend $git commit --no-edit $git --no-pager log --oneline -1 9e1e0eb (HEAD -> master) say fileCopy the code

Cancel partial commits in multiple commits

We developed a feature, and when we launched, the product manager said that some features of the feature were no longer needed, i.e. the submission record and content of the feature could be ignored/deleted.

# roll back the last committed record. $git REVERT 3zJ5SLDL [4] Merge some specific commit. We don't want to merge the entire branch, but rather some commit records of that branch. $git cherry-pick-x z562e23dCopy the code

Use reference logging

How do we recover our lost content and records?

As we mentioned earlier, using the following commands to roll back content, force push code, and delete local branches is a very dangerous operation because there is no way to find the changes after the reset.

$git branch -d <branch_name>Copy the code

Git has a backdoor that allows you to use the relflog command to retrieve the previous content, but it’s a bit more cumbersome. The principle is very simple, that is, when we use Git command operation repository, Git secretly help us to record all operations.

$git --no-pager log --oneline -1 4bc8703 (HEAD -> master) HHHH $git reset --hard HEAD~1 $ git reflog 6a89f1b (HEAD -> master) HEAD@{0}: reset: moving to HEAD~1 4bc8703 HEAD@{1}: commit (amend): $git cherry-pick 4bc8703Copy the code

Batch change history commit

Batch change history submission is not often used, but understanding can save a lot of time!

The previous commands were used to modify one or more commit information. What if we needed to modify the commit history globally? Of course, Git also supports global change history commit, such as global change mailbox address, or delete or modify a file from the global history.

  • The open source project uses the company email for submission
  • The submission file contains private password related information
  • Commit large files to repository code

Here, we can use filter-brach to modify, but it is recommended to create a branch before using it, and operate on the trunk after testing it without any problems, so as to avoid problems and take a heavy burden on yourself.

$git filter-branch --commit-filter 'if ["$GIT_AUTHOR_EMAIL" == $git filter-branch --commit-filter' if ["$GIT_AUTHOR_EMAIL" == "[email protected]" ]; then GIT_AUTHOR_NAME="escape"; GIT_AUTHOR_EMAIL="[email protected]"; git commit-tree "$@" else git commit-tree "$@" fi' HEADCopy the code

Be flexible with hook functions

Git /hooks example hook functions from the.git /hooks directory.

Git has two classes of client-side and server-side hook functions. Client-side hook functions are called when operations such as commit and merge are performed. The server-side hook function is the step of code review and continuous integration when the server receives the code submission. As developers, we don’t set up Git servers, so it’s basically not involved.

The following is an example of a Git hook script that uses the.sample suffix to indicate that it is not enabled. If you want to enable. Sample, delete it as a 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 # Does not push commit commit containing WIP. -rwxr-xr-x pre-rebase -rwxr-xr-x pre-receive.sample -rwxr-xr-x prepare-commit-msg.sample -rwxr-xr-x update.sampleCopy the code

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

The normal code entry process is that we make local changes, make a PR request and pass Github’S CI check, then do a code review, and finally be merged into the main trunk. However, it is a good practice to ensure that the code will not have basic syntax errors before it is submitted, such as through flake8 and PEP8 standards.

Pre-commit is Github’s open source project, which is essentially a script that adds hook functions to a project to ensure that code quality is checked before submitting or pushing it.

The pre-commit-hooks project contains hook scripts that are now supported out of the box. The corresponding content of the hook script is written using Python syntax.

$PIP install pre-commit $pre-commit install -f --hook-type pre-push # Configure the check to be performed $cat Yaml repos: -repo: https://github.com/pre-commit/pre-commit-hooks rev: v2.9.2 hooks: -id:. Trailing -whitespace - id: flake8 # check $git push origin master when executing the pushCopy the code

Rapid cloning of large projects

On large projects, pull code takes up a lot of time!

One of the first problems we encounter when contributing to a large project like Linux or Python is that we quickly clone the project locally. Due to the huge history of project submission and the huge warehouse, plus the problems of domestic network, our enthusiasm may be reduced when the project is completely pulled down.

We can use the –depth parameter to pull the latest commit history from the remote repository. This does not contain the project history. The objects in the.git/objects/ directory are only local and do not contain objects generated by previous changes.

$git clone http://xxx.xx.xxx/xxx --depth=1 If we use the Clone command directly, we cannot do this. We need to perform the following operations to solve the problem perfectly. $git init xxx-15-0-1 $git remote add origin http://xxx.xx.xxx/xxx $git -c protocol. Version =2 15.0.1 --depth=1 $git checkout FETCH_HEADCopy the code

This is pretty much enough for everyday use, but unfortunately, you are now in a machine learning project that contains a lot of LFS files, and clone will now be very slow. To avoid this, Git tools actively pull LFS files to reach the directory.

$GIT_LFS_SKIP_SMUDGE=1 git clone http://xxx.xx.xxx/xxxCopy the code

How do I handle work interruptions

If in the multi-way operation, can also be efficient development!

For example, if we are adding a small feature to a project in a branch, the product manager comes to you and says there is a bug in the online environment that needs to be fixed. However, at this point the little functionality we added is not complete.

If we switch directly to the trunk branch at this point, we will bring all the content that the branch did not commit, which we do not want to do. At this point, we need to save the working status of the last branch and continue working after we have fixed the online bug.

Fortunately, Git also helps us to think about this problem. We can use the Stash subcommand to save changes in the current workspace and staging area to the stack. When it’s time to process, pop up the contents of the stack and start developing again.

➜ stash -h usage: git stash list [<options>] or: git stash show [<options>] [<stash>] 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 change without committing the commit $git stash # Save the current state including untracked file $git stash -u # Show all stashes information $git Stash list # Return to a Stash state $ Drop $git stash@{n}> # return to the state of the last stash and remove the stash information $git stash pop # $git checkout <stash@{n}> -- <file-path> $git checkout <stash@{n}>Copy the code

A safer bet is to push all the current changes and save them to a remote repository. The advantage of this is that we can back up our changes remotely without fear of local file loss and so on. When we need to continue development, pull down the content and try to remedy it by using –amend or reset.

$amend $git commit -- amend-m "some_info" # Back to the specified version and record the changes (--mixed) # $git reset a87f328 $git reset HEAD~ $git reset HEAD~2 $git reset <tag>~2 $git reset --mixed $git reset --soft <commit/reference> $git reset --hard <commit/reference>Copy the code