0

Lets say I create a GIT branch like this:

git clone <main repository>
cd <main repository>
git checkout develop
git branch test/udp_client
git checkout test/udp_client

Or like this:

git clone <main repository>
cd <main repository>
git branch develop/test/udp_client
git checkout develop/test/udp_client

Question A: Is the end result the same?


Question B: How would I do this using git worktree?

71GA
  • 1,132
  • 6
  • 36
  • 69
  • 1
    For Question A: the end results are *usually* the same. Except that the result is not what you expect; the result of `git checkout develop` is not used in `git branch test/udp_client` the way you expect so the end result is branch `test/udp_client`, not `develop/test/udp_client`. The new branch initially points to the same commit as `develop`; these 2 commands can be combined into one: `git branch test/udp_client develop`. All 3 commands can be combined into one: `git checkout -b test/udp_client develop`. – phd Dec 03 '22 at 13:36
  • 1
    But in your case there is major problem: once you have a branch `develop` you cannot create a branch `develop/test/udp_client`. See https://stackoverflow.com/a/2527452/7976758 – phd Dec 03 '22 at 13:37
  • @phd It would be really nice if you could draw an image and post an answer. :) – 71GA Dec 03 '22 at 18:22

1 Answers1

1

Let's go step by step comparing the 2 code blocks. Block №1:

git checkout develop
git branch test/udp_client
git checkout test/udp_client

What it does: it checks out (or create from remote) branch develop. It creates a new branch test/udp_client (but not develop/test/udp_client; the name of the current branch is not used in creating a new branch) pointing to the same commit as the current branch (the current is develop). Then it checks out the new branch. The last 2 commands in the block can be combined into one command: git checkout -b test/udp_client. Branch develop is not required to be the currently checked out branch — the command git checkout -b test/udp_client develop creates a new branch pointing to the same commit as develop and checks out the new branch; so the command replaces all 3.

The second block

git branch develop/test/udp_client
git checkout develop/test/udp_client

is very similar. If we ignore the existence of branch develop in the repository what the block does is: it creates a new branch develop/test/udp_client pointing to the same commit as the current branch; the current branch is not necessary develop, it's most probably main or master. Then the code checks out the new branch.

Unfortunately there is already branch develop so the 2nd block fails with cryptic error message "fatal: Failed to lock ref for update: Not a directory" or "fatal: Failed to lock ref develop/test/udp_client for update: branch develop already exists". The problem is slashes are used in branch names exactly as path separators: branches are stored as files and branches with slashes are stored as directories with the leaf (last path component) as a file. You cannot have develop both as a directory and a file at the same time. I.e., if you have branch develop you cannot create develop/test/udp_client and vice versa — if you have branch develop/test/udp_client you cannot create branch develop.

I cannot answer Question B as I don't use worktrees — I use a lot of submodules and worktrees are incompatible with submodules so I just use separate clones.

phd
  • 82,685
  • 13
  • 120
  • 165
  • Thank you. The part: *"Branches are stored as files and branches with slashes are stored as directories with the last path component stored as a file. You cannot have `develop` both as a directory and a file at the same time. Therefore if you have branch `develop` you cannot create `develop/test/udp_client` and vice versa."* made it clear. – 71GA Dec 03 '22 at 19:23