Continued from the previous article: Git Worktree advanced use, which is much more refreshing

Keywords: Java


Last article Git Worktree Dharma is really fragrant Let's learn how git worktree helps me work in multiple branches at the same time without affecting each other. However, the directory where the worktree is created is not under the current project. I always feel that these created WorkTrees do not belong to the current project, which is very uncomfortable for me with disk management obsessive-compulsive disorder. Today I'll take you to learn about an advanced usage to solve this pain point

Preparation knowledge

Before using advanced usage, you need to know a little about bare repo. Let's start with the commands you are familiar with

git init
git clone

These two commands will generate a non bare repo. We usually do our daily work in this repo. You can add/commit/pull/push here

To generate a bare repo is also very simple, just add the -- bare parameter to the above two commands

git init --bare
git clone --bare

To execute the two clone commands and look at the contents of the file, you will see the difference

  1. Bare repo only contains Git related information, not our actual project file (. java/.js/.py), while non bare repo contains all our information
  2. bare repo names are suffixed with. git by default, which proves the first point
  3. The. git folder does not exist in bare repo, which makes it impossible to add/commit/pull/push like non bare repo

Seeing this, you may feel that bare repo is a Git empty shell folder, which is good for nothing. In fact, these features of bare repo (which cannot be changed) prevent the contents of repo from being messed up, so it can be used for private centralized repo. As explained in a figure, it is actually like this:

If you are interested, you can experiment the whole process locally according to the following command:

user@server:$~  git init --bare name_to_repo.git

user@machine1:$~ git clone user@server:/path/to/repo/name_to_repo.git .
user@machine1:$~ cd name_to_repo
user@machine1:$~ touch README
user@machine1:$~ echo "Hello world" >> README
user@machine1:$~ git add README
user@machine1:$~ git commit -m "Adding a README"
user@machine1:$~ git push origin master

user@server:$~ ls /path/to/repo/name_to_repo.git/
branches/ config description HEAD hooks/ info/ objects/ refs/

user@machine2:$~ git clone user@server:/path/to/repo/name_to_repo.git .
user@machine2:$~ ls name_to_repo.git/
user@machine2:$~ cat README
Hello world

The experimental result is that no matter how you push the file under machine1, there will be no file you push in bare repo, only Git related information. However, when machine2 clone the latest repo, you can see the file of machine1 push, which is the magic of Git

Here, bare repo explains. Next, the next one Git Worktree Dharma is really fragrant Content, with the help of the characteristics of bare repo, you can optimize the practice of working in multiple branches at the same time

Git Worktree advanced usage

First, create a separate folder for your project (for example, amend crash demo) in the directory you selected, and cd it in

mkdir amend-crash-demo
cd amend-crash-demo

Next, clone the project code in the form of bare, and clone the contents into the. Bare folder:

git clone --bare .bare

We also need to create a. git file in the current directory. The contents of the file point to our. bare folder in the form of gitdir (if you don't understand the meaning of gitdir, please go back to it) Git Worktree Dharma is really fragrant )

echo "gitdir: ./.bare" > .git

Then we need to edit the. bare/config file and modify the [remote "origin"] content to be consistent with the following content (that is, add line 6), which ensures that we can create a worktree switch branch and display the correct branch name

vim .bare/config

# -----------------------------------------------
 [remote "origin"]
       url =
       fetch = +refs/heads/*:refs/remotes/origin/*

Next, we can create a worktree. First, we need to create a worktree for the main branch, because the commit ish pointed to by the main branch HEAD is the commit ish of other WorkTrees you create

git worktree add main

# --------------------------------
Preparing worktree (checking out 'main')
HEAD is now at 82b8711 add main file

Usually, instead of working directly on the main branch, we create other types of branches and continue to create a worktree named feature/JIRA234-feature3

git worktree add -b "feature/JIRA234-feature3" feature3

# ------------------------------------------------
Preparing worktree (new branch 'feature/JIRA234-feature3')
HEAD is now at 82b8711 add main file

Looking at the contents of the current folder, you will find that there are only two folders: main and feature3 (because. bare and. git are hidden folders / files). Isn't this quite refreshing?

ls -l

# -------------------------------------------
total 0
drwxr-xr-x  10  rgyb  staff  320 Nov 23 21:44 feature3
drwxr-xr-x  10  rgyb  staff  320 Nov 23 21:36 main

ls -al
# -------------------------------------------
total 8
drwxr-xr-x   6  rgyb  staff  192 Nov 23 21:44  .
drwxr-xr-x   3  rgyb  staff   96 Nov 23 21:14   ..
drwxr-xr-x  12  rgyb  staff  384 Nov 23 21:36  .bare
-rw-r--r--   1  rgyb  staff   16 Nov 23 21:29   .git
drwxr-xr-x  10  rgyb  staff  320 Nov 23 21:44  feature3
drwxr-xr-x  10  rgyb  staff  320 Nov 23 21:36  main

Next, we can do add/commit/pull/push operations on our various branches without affecting each other

echo "feature3 development" > feature3.yaml
git add feature3.yaml

git commit -m "feat: [JIRA234-feature3] feature3 development"
# ------------------------------------------------------------------
[feature/JIRA234-feature3 aeaac94] feat: [JIRA234-feature3] feature3 development
 1 file changed, 1 insertion(+)
 create mode 100644 feature3.yaml

git push --set-upstream origin feature/JIRA234-feature3

Through the four commands of worktree in the previous article, multi branch collaborative development is no longer a problem:

git worktree add
git worktree list
# ------------------------------------------------------------------------------------------------
/Users/rgyb/Documents/projects/amend-crash-demo/.bare        (bare)
/Users/rgyb/Documents/projects/amend-crash-demo/feature3   aeaac94 [feature/JIRA234-feature3]
/Users/rgyb/Documents/projects/amend-crash-demo/main        82b8711 [main]

git worktree remove
git worktree prune


With the help of the feature of bare repo, we can manage all WorkTrees in the current project directory very neatly, and multi branch collaborative development, like this:

└── amend-crash-demo
    ├── feature3
    │   ├──
    │   ├── config.yaml
    │   ├── feat1.txt
    │   ├── feature3.yaml
    │   ├── file1.yaml
    │   ├── hotfix.yaml
    │   ├──
    │   └── main.yaml
    └── main
        ├── config.yaml
        ├── feat1.txt
        ├── file1.yaml
        ├── hotfix.yaml
        └── main.yaml

3 directories, 15 files

If you have disk management obsessive-compulsive disorder, this is definitely a good way.

If you want to better understand the whole process, you need to check the Git related file information while operating the commands in this article

If you have any questions, please communicate in the message area

reference resources


Rigong Yibing | original

Posted by minou on Thu, 25 Nov 2021 16:54:29 -0800