background

Keep a clean Git submission record, three tips are enough. After reading this, everyone commented privately that this is a very useful feature. I suddenly thought of another Git feature that I use at work that is also quite useful and must come clean

As programmers, we should all have a feeling that once you enter a project, you will be responsible for everything from development, release and production, to hotfix and post-maintenance. When you are developing a feature, it is quite common for the boss to suddenly ask you to do hotfix for production. Faced with this situation, Those of us who use Git usually have two solutions:

  1. Commit unfinished features hastily, then switch branches to hotfix
  2. git stash | git stash popSave work temporarily, then switch to Hotfix

The second way is much better than the first one, but stash is still not a good solution for the following scenarios

The scene we face

  1. Running a long test on the main branch, switching to hotfix or feature breaks the test
  2. Projects are very large, with frequent index switching and very high cost
  3. There are old versions released several years ago, the Settings are different from the current ones, and the switch of IDE Arms adaptation will also bring great overhead
  4. To switch branches, you need to reset the corresponding environment variables, such as dev/qa/prod
  5. You need to switch to a colleague’s code to help debug code recurrence problems

Git clone multiple repOs. This is one way to solve the above problems, but it also hides a lot of problems:

  1. The state of multiple repOs is not synchronized well, for example, there is no quick cherry-pick, a branch of one repo checkout, and another repO needs to checkout again
  2. Git history/log is repeated when the project history is very long,.gitThe contents of folders are very disk intensive
  3. Multiple REPOs on the same project can be difficult to manage

So how do you satisfy these particular scenarios without having these problems?

git-worktree

Git worktree supports Git worktree since 2015, but few people know about it.

git worktree --help
Copy the code

You can quickly see the help documentation:

The purpose of git-worktree is:

You can maintain a single REPO and work on multiple branches at the same time without affecting each other

There are many red box commands above, but we use only the following four commands:

 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>]
Copy the code

Before we get started, there are two Git facts that you might not have noticed:

  1. By default,git initgit cloneThere is only one initialized REPOworktreeThat is calledmain worktree
  2. If you use Git in a directory, it is either present in the current directory.gitFolder. Or have a.gitFiles, if only.gitThe contents of the file must be pointed to.gitThe folder

The second sentence feels quite round, below uses the example to illustrate, is easy to understand

git worktree add

The current project directory structure looks like this (amend-crash-demo is the root of the repo) :

└─ amend-crash-demo 1 directoryCopy the code

CD amend-crash-demo Run 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
Copy the code

Look again at the directory structure

└── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ──Copy the code

By default, this command creates a branch named Feature2 based on the commit-ish location of the HEAD (or, optionally, any commit-ish in the Git log), as shown in the structure above

cd .. /feature/feature2/ You can see that there is a.git folder in this branch, instead of a.git folder.

gitdir: /Users/rgyb/Documents/projects/amend-crash-demo/.git/worktrees/feature2
Copy the code

Here, you understand the above knowledge point 2, is it a lot clearer?

From there, you can do anything you want on the Feature2 branch (add/commit/pull/push), independent of the Main Worktree

In general, the project team has a certain branch naming convention, such as feature/ jiraid-title, hotfix/ jiraid-title. If you just follow the above command to create a worktree, the/in the branch name will be treated as a file directory

git worktree add .. /hotfix/hotfix/JIRA234-fix-namingCopy the code

After running this command, the file directory structure looks like this

. ├ ─ ─ amend - crash - demo ├ ─ ─ feature │ └ ─ ─ feature2 └ ─ ─ hotfix └ ─ ─ hotfix └ ─ ─ JIRA234 - fix - naming six directoriesCopy the code

This is obviously not what we want, so we need support for the -b parameter, just like git checkout -b

Execute command:

git worktree add -b "hotfix/JIRA234-fix-naming" .. /hotfix/JIRA234-fix-namingCopy the code

Take a look at the directory structure

. ├ ─ ─ amend - crash - demo ├ ─ ─ feature │ └ ─ ─ feature2 └ ─ ─ hotfix ├ ─ ─ JIRA234 - fix - naming └ ─ ─ hotfix └ ─ ─ JIRA234 - fix - naming 7 directoriesCopy the code

Enter the jira234-fix-naming directory, which is in the hotfix/ jira234-fix-naming branch by default

Worktrees are easy to set up, unmanaged, and the project directory structure is cluttered, which we don’t want to see, so we need to have a clear idea of what worktrees a repO has set up

git worktree list

All worktrees share the same REPO. Therefore, you can run the following command in any worktree directory to view the worktree list

git worktree list
Copy the code

After executing the command, you can view all the worktree information created above, and the 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]
Copy the code

If you want to delete worktree, you will waste a lot of disk space

git worktree remove

Worktree: remove worktree: remove worktree: remove worktree

git worktree remove hotfix/hotfix/JIRA234-fix-naming
Copy the code

At this point, 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]
Copy the code

If you create a worktree and make changes to it, and suddenly the worktree is no longer needed, you can’t delete it by following the above command. You need the -f parameter to help

git worktree remove -f hotfix/JIRA234-fix-naming
Copy the code

We removed worktree, but there are still many administrative files that are not used in Git files, so we need to clean them further

git worktree prune

This command is the clean bottom operation that keeps our work clean at all times

conclusion

You should understand that the entire process of using Git-worktree consists of the following four commands:

git worktree add
git worktree list
git worktree remove
git worktree prune
Copy the code

Git workTree differs from git Clone with multiple repOs. Maintain a single REPO, create multiple worktrees, and operate smoothly

My practice: Git worktree is usually used. I will unify the directory structure. For example, the feature directory stores all feature worktrees, and the hotfix directory stores all hotfix worktrees. This prevents the entire disk directory structure from becoming cluttered by creating multiple worktrees

I’m a bit obsessive about disk management. Ideally, the worktree of a particular repo would be placed in the repO’s file directory, but this would result in all files under the newly created worktree created by Git Track. It’s definitely not a good idea to go back and forth and modify the Gitignore file to avoid Git track worktree content, but I’ll show you a better way in the next section

Soul asking

  1. Can I delete main Worktree? why
  2. Do you understand the changes in the repo/.git/wortree directory?

Personal blog: https://dayarch.top

Day arch a soldier | original