I don't know if I have a fundamental misundertanding about what a worktree is or what, but, I have tried fixing some bugs on a worktree. Used the git worktree add command to make it. I navigated to the folder it created, made my changes, made a commit, and now I am ready to push to the commit to a remote branch so I can create a Pull Request.
This is my workflow when doing good old fashioned git branches. I will:
- create a local branch
- make changes
- stage changes
- commit staged changes
- Push and set upstream branch
- Create a PR
With my worktree I am stuck on step 5.
- create worktree
git worktree add <path> - make changes
- stage changes
- commit staged changes
- Push and set upstream branch
- Refspec error
When I try to push with --set-upstream I get the src refspec <branch> does not match any error. I then looked for the .git folder to find that there wasnt one, just a .git file with the path to that worktree.
There are a lot of tutorials out there on worktrees, and every one I have tried to read/watch has skipped this crucial detail. They tend to just cover the add/remove commands.
Is a worktree even considered a branch? I didnt think so at first but git branch now shows me as being on a branch with the name of my worktree, interstingly, and unexpectedly it also shows that branch as being under another branch I was working on as if it were a sub branch of some kind
$ git branch
+ 371601_TLS_Certificates
* 395275_396239_MVPbugs
aspire-dev-shell-baseurl
ls
+ main
users/rrhughes/US/371601_TLS_Certificates
users/rrhughes/US/383751_resolve_URL
users/rrhughes/US/383751_settings_NXupdate
users/rrhughes/US/383751_settingsui
users/rrhughes/US/settings_devops
Later via brute force attempting to find a solution I tried a bare git push and git told me it was not tracking a remote branch (as expected). It then provided me with this command
git push --set-upstream origin <my branch name>
I copy pasted it and it worked. However, this is nearly identical to the command I was trying before, and the command that I use to set upstream from regular git branches. the only difference was the name of my branch. It is a standardization on my dev team to make remote branches under a file structure for easy navigation and organization, so my command usually looks like this.
git push --set-upstream origin users/username/bugs/<my branch name>
Updated Question(s): So I am still confused why this did not work. Do I need to name my local worktree exactly what I will name it in the remote? If I want to name my local branch something simple, how do I set it to track a remote with a different name that meets my teams remote branch naming standard?
-Original Question: how do I get these changes on this worktree into my remote repo so I can create a PR?-
You need to
--set-upstreamwith a refspec:Or using this shortcut as LeGEC suggested for pushing the currently checked out branch:
Now the easiest thing to do if you’re using git-pull(1) is to use
git pull originwhile you are checked out on that branch:Because note that the following will not work as you probably intend/expect:
Elaboration on why git-worktrees(1) is irrelevant
Switch to a new worktree and create branch
users/kristoffer/demo/update-readme(note thegit worktreecommand):This worked.
(See section “Annex: git-worktrees/remote demonstration” for a full script that you can try on your machine.)
What branch am I on?
*is the currently checked out branch. What’s the+in front ofmain?According to
man git-branch:[1]So what happens if I change back to the directory I was in before I changed directory into the worktree?
Makes sense:
mainis the checked-out branch since this is the branch that this worktree is ondemo) is marked with+(the mark for a branch checked out in another worktree)What is a worktree?
First you need to understand what a “working tree” is:[2]
A “worktree” is a working tree plus repository metadata, with the repository metadata mostly “shared among other worktrees of a single repository”[3] [4].
Also:
When you did
git init, you made a repository with one worktree. When you didgit worktree addyou created the second worktree (more on this in the section “Back to basics (init)”).Is a worktree even considered a branch?
No, and these things have nothing to do with each other.
A branch was created for you with the base name of the worktree since you gave:
I.e. you didn’t provide the optional
commit-ishafter the branch:[5]Unpacking “push git worktrees to a remote branch”
When you push a branch to a remote repository, you are pushing a ref. A ref doesn’t care what your working tree looks like (e.g it could be “dirty” but that doesn’t affect the ref). In fact a remote repository is likely to be “bare”, which means that it doesn’t have a working tree.
So the sentence by itself does not make sense.
But what was clearly meant was:
Which does make sense if you are using something like
git pushwithout explicitly giving the branch name, since then you want whatever branch is checked out to be pushed.Then the standard troubleshooting applies:
git config) allow me to saygit push origin(note: no branch)?Back to basics (init)
Given this blank slate:
What’s the worktree and branch in this case?
The exact same principles apply since a non-bare repository like this one has one worktree, i.e. the one where you are right now; this is the “main worktree”.[6] If you started using
git worktree addthen you would be creating “linked worktrees”.[6]So then we can ask ourselves again:
git config) allow me to saygit push origin?And these questions turn out to be much more elementary since the worktree is in fact mostly a distraction from the real problem.
Notes
On
git version 2.40.0man gitglossary, entry “working tree”man gitglossary, entry “worktree”The non-shared metadata “are maintained separately per worktree (e.g. the index, HEAD […]” (ibid)
From
man git worktree, under subcommandadd:man git worktreeAnnex: branches/worktrees/remote demonstration
This shell script demonstrates how branches, worktrees, and remotes can interact: