8

TLDR: If X exists as a remote branch, then git checkout X should create a local branch of it. In my case, for a single branch, it does not.

The remote repository has a master, release, and some other branches (say refactor-update) I do:

git clone WHATEVER/repo.git
git checkout release

But I do not get the normal branch switch message, nor is a local branch tracking origin/release created (per the man page for git checkout). I am still on master. Note that if I do git checkout refactor-update everything works as expected.

This is reproducible on other computers (though the same platform and likely the same version of git). I have (out of desperation, not because I thought it would work), removed the release branch and replaced it with a backup and master respectively with no change in behaviour (git push origin :release && git push origin master:release)

I am stuck for what might be causing the problem. My suspicion is that git checkout doesn't seem to recognize the word release for some reason, which would make it much like executing just git checkout. To try and follow up on this, in another repo I created a release branch to see if it was a reserved word or something, but it is definitely just in this repository. There doesn't seem to be anything out of the ordinary in .git/config.

Git version: 1.8

Anshul Goyal
  • 73,278
  • 37
  • 149
  • 186
medwards
  • 218
  • 1
  • 11
  • Did you forget to fetch the remote branches maybe? Try a `git fetch --prune` and then the same `git checkout X` – Miguelgraz Sep 16 '13 at 17:16
  • I have tried `git fetch` but not with `--prune`. Doesn't this just remove remote branches which no longer exist from my local? – medwards Sep 16 '13 at 17:58
  • Yes, `-p` / `--prune` only adds the "remove unmatched" behavior, the pick-up stuff is always enabled (well, provided you have not broken the git config `fetch =` line for the remote :-) ). – torek Sep 16 '13 at 18:01
  • `--prune` didn't have different behaviour than normal `fetch.` I tried to create a nearly empty repo with no private info to provide as a reproduction step and then the release branch started working. Sadly, I have no use for a repo in which I deleted all the files and replaced them with an empty `TESTFILE` :P – medwards Sep 17 '13 at 17:38
  • As an experiment I executed `gitk somebranchonlyontheremote` and as expected gitk says 'wut?' I then did `gitk release` (with no local branch named `release`) and it showed me a history... – medwards Sep 17 '13 at 17:40
  • 1
    Does the root folder of your project contain a file or folder with the same name as the branch that you want to check out? That is, is there a file/folder `repo/release`? That was part of the problem for me. Which version of git are you using? – jcsahnwaldt Reinstate Monica Sep 24 '13 at 20:12
  • Possible duplicate of [git checkout master does not switch branch - repository broken?](https://stackoverflow.com/questions/34287722/git-checkout-master-does-not-switch-branch-repository-broken) – BobbyA Jun 12 '18 at 16:08

4 Answers4

4

In my case, the problem is that I have a folder with the same name as the branch in the root of my project. Git seems to think the xyz in git checkout xyz is the folder, not the branch.

I had to do the following to switch my working tree to branch xyz for the first time:

git checkout -t origin/xyz

Apparently, this adds a few lines to .git/config (and maybe other configuration files). After that, I can switch between xyz and master just by calling git checkout xyz / git checkout master.

When I'm in the root folder and call git checkout xyz right after I cloned the repo, git does nothing and doesn't give any response either. When I cd to a sub-folder so that the folder xyz is not in scope anymore and then call git checkout xyz, git complains: error: pathspec 'xyz' did not match any file(s) known to git.

  • 2
    That looks like a bug -- you should write up a reproducer and send a bug report in to the git mailing list. – torek Sep 24 '13 at 20:10
  • I just tried again with git version 1.7.9.5 on a different system - same behavior. Either I misunderstand / misremember how `git checkout xyz` is supposed to work, or GitHub has made some strange changes since I last cloned my repo. :-( – jcsahnwaldt Reinstate Monica Sep 24 '13 at 20:34
  • What do you mean by "magic DWIM for `-b`"? I just tried `git checkout -b xyz` on 1.8.3.2, and it just creates a new branch without a connection to the remote branch. – jcsahnwaldt Reinstate Monica Sep 24 '13 at 21:21
  • I edited my answer: the problem is caused by a folder that has the same name as the branch. With a branch for which no such folder exists, `git checkout foo` works as expected. – jcsahnwaldt Reinstate Monica Sep 24 '13 at 21:26
  • 1
    I mean, the fancy "oh wow that's a branch name not a path name" thing (where you don't need `-b`). I'm always leery of DWIM in the first place, it leads to situations like the one you ran into where a branch name and a path element match. – torek Sep 24 '13 at 22:15
  • @torek on the other hand, checking out pathnames without the `--` separator is just as much a DWIM, but I'd hate to lose it. – jthill Sep 25 '13 at 10:44
  • 1
    @jthill: lucky for you I'm not in charge of git commands, perhaps. :-) I'd probably split "checkout" into at least two completely different commands, one to "switch to (optionally creating) branch" and one to "extract file(s) from current or named branch". – torek Sep 25 '13 at 10:55
  • 1
    It might be a bug, but it is the correct answer. I removed the `release` folder and now `git checkout release` works as expected. @JonaChristopherSahnwaldt, @torek: thanks for staying on this and assuming I'm not a git newbie who has never seen the `-b` or `-t` arguments. – medwards Sep 26 '13 at 13:05
  • 1
    It's a bug and the fixes are being bandied-about on the git email list. There's disagreement whether `git checkout x` means *branch* `x` or *path* `x` when both are possible, but `git checkout x --` should *definitely* mean "branch `x`" and it's just broken. – torek Sep 26 '13 at 13:09
1

Clone gives you remotes for all the origin's branches, but it only gives you a local branch for the origin's HEAD branch (or any other branch on request).

TLDR: If X exists as a remote branch, then git checkout X should create a local branch of it. In my case, for a single branch, it does not.

I'll venture to disagree with that. If you want checkout to create a branch, tell it to create a branch.

git checkout -t origin/release     # create branch `release` tracking `origin/release`.

git checkout -b foobar             # create branch `foobar` based on your HEAD commit

[edit:]

I think I understand the complaint now.

git checkout name does:

  • if it's local branch or explicit remote branch, switch to it.
  • if it's a tracked path, reset it
  • if it's a remote branch, create a tracking branch and switch to it.

and because it prioritizes the reset it can choose to do something unsafe when it could have chosen to do something safe.

jthill
  • 55,082
  • 5
  • 77
  • 137
  • 2
    The confusing thing is that `git checkout foo` usually *does* check out the remote branch - unless there is a file/folder called `foo`. So I'll venture to disagree with your disagreement. ;-) – jcsahnwaldt Reinstate Monica Sep 25 '13 at 09:16
  • live and learn. A remote breaking my path checkouts by adding a bad branch name alarms me as much as breaking that nifty implicit-tracking-branch-creation checkout with a bad pathname alarms you. I agree with @torek's comment, this behavior is so unpredictable it's in bug territory. git should warn when both conveniences might apply rather than silently picking the one I like. – jthill Sep 25 '13 at 10:38
0

You are missing the -b option

Try doing

git checkout -b branch_name

Edit Note: As discussed in comments below, this would be the case only if you were using git version 1.7.9 or lesser, which I had been at the time.

Anshul Goyal
  • 73,278
  • 37
  • 149
  • 186
  • Is the `-b` option necessary even if the branch exists remotely? – Miguelgraz Sep 16 '13 at 17:26
  • @Miguelgraz `git checkout branch_name` will switch between branches only if they exist locally. Since the branch does not exist on your local repo, you need the `-b` flag to create a branch and switch to it in one go. – Anshul Goyal Sep 16 '13 at 17:30
  • 2
    Actually, it depends on your particular version of git. With quite new versions, you don't need `-b` anymore, git auto-detects that you don't have a `foo` branch but there is a `remotes/origin/foo` so it does an implied `-b foo origin/foo`. – torek Sep 16 '13 at 17:34
  • @torek can you tell the particular versions beyond which this works? I seem to have an older copy, and same could be true for OP :) – Anshul Goyal Sep 16 '13 at 17:38
  • @ansh0l: Note I said "per the man page for git checkout" which specifically states my use case should work. Not only that I outline how my use case works for other branches. In my case I am running something in the 1.8 branch. – medwards Sep 16 '13 at 17:57
  • 1
    I saw this in the 1.8.3.2 release notes. The 1.6.1 release notes mention adding `git checkout --track origin/hack` as a way to create the local branch `hack`, too, but 1.8.3 is probably the first one to do it by just naming the remote branch without `origin/`. – torek Sep 16 '13 at 17:58
  • `git checkout -b x` doesn't work for me (git 1.8.3.2 on a Mac). It says `Switched to a new branch 'x'` but doesn't change the working tree. If I add the branch to .git/config first, git says `Switched to a new branch 'x'` but also `Your branch and 'origin/x' have diverged` and tells me to do `git pull`. When I run `git pull`, git tries to merge branch x into my local copy of the master branch, which results in a big mess. – jcsahnwaldt Reinstate Monica Sep 24 '13 at 19:05
0

You're missing the -t option.

git checkout -t origin/release

will create and check out the local branch release that tracks origin/release.

With newer versions of Git, this is enough:

git checkout release
SzG
  • 12,333
  • 4
  • 28
  • 41