0

I like git worktree, but keep getting into situations where the local working directory is not the same as the remote branch, even though git pull says "Already up to date".

Here's a little MRE I did:

  • Created a remote repo in the GitLab web interface.
  • Cloned it using git clone --bare <url>
  • Added the main branch locally using git worktree add main
  • Added a new branch using git worktree add new-branch, cded into it and did a git push.
  • Using the GitLab web interface, I added a file main-branch-change-1 directly in the main branch, then rebased new-branch on top of the new main, then added a second file feature-branch-change-1 in new-branch.
  • git pull on the local new-branch says "Already up to date", while commit hash and git log clearly shows the local is not up to date. The file main-branch-change-1 is present, but not feature-branch-change-1.
  • git fetch --all in the bare repo followed by git pull in new-branch changes nothing.
  • git pull in the main branch followed by git pull in new-branch changes nothing.

What do I have to do to sync these changes?

Some screenshots:

GitLab graph remote graph

Content of remote new-branch remote new-branch content

Locally local state

Daniel Hjertholm
  • 177
  • 1
  • 2
  • 16
  • 1
    `git pull` means *run `git fetch`, then run a second Git command*, with `git merge` being the default second command. With no options, `git merge` means *merge with upstream*, so what `git merge` in the added working tree will merge *with* depends on what the *current branch* is in that added working tree and then on what that branch's upstream is set to. Use `git branch -vv` to view the upstream setting for each branch name. – torek Dec 20 '22 at 11:41
  • 2
    Generally, you never want to use `git fetch --all`: that means *all remotes*, which is pretty rare to want (and if you do want it, `git remote update` is usually what you want to use). – torek Dec 20 '22 at 11:42
  • 1
    Your main mistake here, though, is using `git clone --bare`. Don't do that *unless* you want to create a repository where the only thing you'll do with it is receive `git push` requests. As it is, you've set up a repository where `git fetch` does not create or update remote-tracking names; that's why `git merge` is doing nothing, as none of the upstreams are updating. – torek Dec 20 '22 at 11:45

2 Answers2

3

As torek pointed out in a comment, the issue was caused by cloning with --bare. That's something I picked up from "ThePrimeagen" here (2 mins in). But rather than having a full (non-bare) repo at the root, which I think I don't want, this command seems to fix it all:

git config --add remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"

Thanks TamaMcGlinn.

I still have to do git branch --set-upstream-to=origin/new-branch new-branch from the new-branch folder, which failed previously with "error: the requested upstream branch 'origin/main' does not exist", but succeeds after the above command.

Daniel Hjertholm
  • 177
  • 1
  • 2
  • 16
0

Added the main branch locally using git worktree add main

This is your main problem. When you run git worktree add whatever git will by default create a new branch called whatever and attach it to the head of the new worktree. This new branch is in no way connected to any branches on any remotes, origin included, even if there happens to be some branch with the same name.

If you want your local main branch to track origin/main that can (and must in your particular case) be done with the following command:

git branch --set-upstream-to=origin/main main

However your usage of worktrees (and bare repository) seems a bit strange and I would strongly recommend not using worktrees yet until you get some more experience. Worktrees are excellent for using git test and possibly as an alternative to using git stash (which I never use)1, but not as an alternative to just switching branches.

1 I recently created a temporary worktree when needing to do something else when I has an interactive rebase with conflict ongoing which I did not want to abandon.

hlovdal
  • 26,565
  • 10
  • 94
  • 165
  • I'm constantly having to review other team members' work, and with worktree I not only have to stash local changes, I also need to install dependencies both when checking out that other branch, and when switching back to my own. But thanks for your suggestions, I'll try them out and report back. – Daniel Hjertholm Dec 21 '22 at 12:16
  • `git branch -vv` shows `main` and `new-branch` mapped to specific commit hashes, but they are apparently not tracking any remotes. `git branch --set-upstream-to=origin/main main` returns "error: the requested upstream branch 'origin/main' does not exist". `git remote` returns `origin`. Suggestions? – Daniel Hjertholm Dec 21 '22 at 12:23
  • `git ls-remote --head` returns `refs/heads/main` and `refs/heads/new-branch`. Would expect them to be called `origin/main` and `origin/new-branch` – Daniel Hjertholm Dec 21 '22 at 12:30
  • `for i in $(git remote); do git branch --all | grep remotes/$i/; done` should give you all remote branches. Does it include main? – hlovdal Dec 21 '22 at 15:46