background
The last article keeps a clean Git submission record. Three enough. 161a41f1593a7e. After you read it, there are private messages saying that this is a very useful function. I suddenly thought of another Git function that I used in my work, which is also quite good. Use, you must tell the whole story
As programmers, we should all have a feeling. Once you enter a project, from development, to release and production, to hotfix, to post-maintenance, you basically have your share. A certain feature is being developed, and the boss suddenly jumped out and said It is more common for you to make hotfixes in production. Faced with this situation, we who use Git usually have two solutions:
- Submit unfinished features hastily, and then switch the branch to hotfix
git stash | git stash pop
Temporarily store the work content, and then switch to hotfix
The second method is much better than the first one, but in the face of the following scenarios, stash is still not a good solution
The scene we face
- Is running a long test on the main branch, switch to hotfix or feature, the test will be interrupted
- The project is very large, the index is frequently switched, and the cost is very high
- There are old versions released a few years ago, and the settings are different from the current ones. The IDE restructure adaptation switch will also bring a lot of overhead.
- To switch branches, you need to reset the corresponding environment variables, such as dev/qa/prod
- Need to switch to the code of a colleague to help debug the code to reproduce the problem
Some students thought, git clone multiple repo is not enough? This is a way to solve the above problems, but there are also many problems hidden behind them:
- The status of multiple repo is not easy to synchronize, for example, there is no way to quickly cherry-pick, one repo checkout branch, another repo needs to be re-checkout
- git history/log is repeated. When the project history is very long,
.git
folder will take up disk space very much. - The same project, multiple repo, not easy to manage
So what can be done to satisfy these special scenarios without these above-mentioned problems?
git-worktree
In fact, this is a feature that Git has been supporting since 2015, but few people know it. The use of git-worktree is very convenient. Type in the terminal:
git worktree --help
You can quickly see the help document description:
To explain the role of git-worktree in simple words is:
Only need to maintain one repo, and can work on multiple branches at the same time, without affecting each other
There are many red border commands above, and we actually only use the following four:
git worktree add [-f] [--detach] [--checkout] [--lock] [-b <new-branch>] <path> [<commit-ish>]
git worktree list [--porcelain]
git worktree remove [-f] <worktree>
git worktree prune [-n] [-v] [--expire <expire>]
Before starting the explanation, we need to share with you two Git knowledge points that you may overlook:
- By default, the repo initialized by
git init
orgit clone
worktree
, calledmain worktree
- Use the Git command in a certain directory, the current directory either has a
.git
folder; or there is a.git
file, if there is only a.git
file, the content inside must point to the.git
folder
The second sentence feels quite convoluted. Let’s use an example to illustrate it. It’s easy to understand.
git worktree add
The current project directory structure is like this ( amend-crash-demo
is the root of the repo):
.
└── amend-crash-demo
1 directory
cd amend-crash-demo
Run command git worktree add ../feature/feature2
➜ amend-crash-demo git:(main) git worktree add ../feature/feature2
Preparing worktree (new branch 'feature2')
HEAD is now at 82b8711 add main file
Revisit the directory structure
.
├── amend-crash-demo
└── feature
└── feature2
3 directories
By default, this command will create a branch named feature2 based on the commit-ish where HEAD is located (of course, you can also specify any commit-ish in git log). The branch disk location is shown in the above structure.
cd ../feature/feature2/
.git
folder does not exist in this branch, but there is a .git
file. Open the file and the content is as follows:
gitdir: /Users/rgyb/Documents/projects/amend-crash-demo/.git/worktrees/feature2
At this point, if you understand the knowledge point 2 above, will it be much clearer?
Next, you can do everything you want on the feature2 branch (add/commit/pull/push), without interfering with the main worktree
In general, the project team has a certain branch naming conventions, such as feature/JIRAID-Title
, hotfix/JIRAID-Title
, if only New worktree follow the above instructions, branch names /
will be handled as a file directory
git worktree add ../hotfix/hotfix/JIRA234-fix-naming
After running the command, the file directory structure is like this
.
├── amend-crash-demo
├── feature
│ └── feature2
└── hotfix
└── hotfix
└── JIRA234-fix-naming
6 directories
Obviously this is not what we want, then we need the support of the -b parameter, just like git checkout -b
Excuting an order:
git worktree add -b "hotfix/JIRA234-fix-naming" ../hotfix/JIRA234-fix-naming
Let's look at the directory structure again
.
├── amend-crash-demo
├── feature
│ └── feature2
└── hotfix
├── JIRA234-fix-naming
└── hotfix
└── JIRA234-fix-naming
7 directories
Enter the JIRA234-fix-naming
directory, the default is on the hotfix/JIRA234-fix-naming
branch
Worktree is easy to set up, without management, the project directory structure is definitely messy, this is what we don’t want to see, so we need to know clearly which worktrees are built in a certain repo
git worktree list
All worktrees share a repo, so in any worktree directory, you can execute the following command to view the worktree list
git worktree list
After executing the command, you can view all the worktree information we created above, main worktree
will also be displayed here
/Users/rgyb/Documents/projects/amend-crash-demo 82b8711 [main]
/Users/rgyb/Documents/projects/chore/chore 8782898 (detached HEAD)
/Users/rgyb/Documents/projects/feature/feature2 82b8711 [feature2]
/Users/rgyb/Documents/projects/hotfix/hotfix/JIRA234-fix-naming 82b8711 [JIRA234-fix-naming]
/Users/rgyb/Documents/projects/hotfix/JIRA234-fix-naming 82b8711 [hotfix/JIRA234-fix-naming]
After the work of worktree is finished, delete it in time, otherwise it will waste a lot of disk space
git worktree remove
This command is very simple. What is the name of the worktree? Just remove it.
git worktree remove hotfix/hotfix/JIRA234-fix-naming
At this time, the hotfix with the wrong branch name is deleted
/Users/rgyb/Documents/projects/amend-crash-demo 82b8711 [main]
/Users/rgyb/Documents/projects/chore/chore 8782898 (detached HEAD)
/Users/rgyb/Documents/projects/feature/feature2 82b8711 [feature2]
/Users/rgyb/Documents/projects/hotfix/JIRA234-fix-naming 82b8711 [hotfix/JIRA234-fix-naming]
Suppose you create a worktree and make changes in it. Suddenly the worktree is no longer needed. At this moment, you cannot delete it according to the above command. At this time, you need the -f
parameter to help.
git worktree remove -f hotfix/JIRA234-fix-naming
Deleted worktree. In fact, there are many administrative files in Git files that are useless. In order to keep clean, we need to clean up further
git worktree prune
This command is a clean pocket operation, which can keep our work tidy all the time
Summarize
At this point, you should understand that the entire process of using git-worktree is the following four commands:
git worktree add
git worktree list
git worktree remove
git worktree prune
You should also understand the difference between git worktree and git clone multiple repo. Maintain only one repo, create multiple worktrees, and flow smoothly between operations
My practice : Usually use git worktree, I will unify the directory structure, for example, store all feature worktrees under the feature directory, and store all hotfix worktrees under the hotfix directory, so that the entire disk directory structure will not change due to the creation of multiple worktrees Get confused
I have some obsessive-compulsive disorder in disk management. Ideally, the worktree of a certain repo should be placed in the file directory of this repo, but this will cause all files under the newly created worktree of Git track, in order to avoid Git track worktree It’s definitely inappropriate to modify the gitignore file back and forth. next section, I will introduce a better way
Soul inquiry
- Can the main worktree be deleted? why
- Can you understand the changes in the repo/.git/wortree directory after repeated creation and deletion of worktree?
Ri Gong Yibing| Original
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。