when git can’t checkout a remote branch

Problem

Coworker has a workflow of:

  1. work on branch
  2. push branch and make PR of it
  3. delete local branch, checkout remote so that local is tracking remote
  4. carry on

except here’s what happened in the checkout stage:

user@host repo-name (master)$ git checkout issue-XXXXX-dummy-name-for-blogpost
 error: pathspec 'issue-XXXXX-dummy-name-for-blogpost' did not match any file(s) known to git.

It’s an old branch he’s trying to check out, but he just did the deletion step in this a few minutes ago. He does this all the time and he’s very experienced, so this was a bit of a pickle. I turned my rubber duckie over in my hands. We ran through some possibilities: doing a git fetch, trying it in a clean git clone (it worked fine), trying git-gc in the clone to see if it would break it, etc. Eventually, we turned to google.

Research

My search, yielded two stack overflow hits, and he told me about another.
They suggested checking git show-ref, and it we decided to diff the good and bad repo’s refs. The SO responses also turned up an explicit way to tell git to check out a remote branch locally and track it:

git fetch origin
git checkout -b test origin/test

His refs had something like the following in them:

bad repo:

user@host bad-repo-name (master)$ git show-ref
ddc955...0f61cb refs/remotes/experiment/issue-XXXXX-dummy-name-for-blogpost
86b183...ac388f refs/remotes/origin/issue-XXXXX-dummy-name-for-blogpost

good repo:

user@host good-repo-name (master)$ git show-ref
86b18399ad7cb01eeea74f5577c0a5dfe1ac388f refs/remotes/origin/issue-20198-remove-easy-cloud-accounting-copy

Solution

This led him to the realization that git must be doing some name-matching and hitting the first instance of the branch name. That ref line tells us that commit ddc955…0f61cb is ref’d as a branch with our name on a remote named ‘experiment’. The other line says that there is a different commit ref’d as a branch with our name on a remote named ‘origin’, which is what we want to check out.

Here’s the problem, and it was the aha moment: the ‘experiment’ remote no longer exists — this commit is old enough to have been used on a nascent form of this repo, when it was an experiment, moved from an existing svn repository. The issue is that the ‘experiment’ commit can’t be checked out, and git (reasonably) gives up at that point.

So he deleted the experiment branch and used the explicit form for checking out a branch from origin to track the remote. Problem solved.

Takeaway

For the future:

  • testing with a clean clone is really useful for determining if your problem is in your repo or everywhere
  • git show-refs is a reallllly useful tool for telling you all the things

agh c++

I come from the land of python, where the grass is green and the trees are leafy. I’m writing a game in C++ for fun, because I’ve never had to do serious work with C++, and so far… it seems like a nightmare-zone.

First, there’s the crufty syntax, full of useless symbols. That’s a known cost though, visible to any passer-by. Second, there’s type definitions — I have to figure out specific types just to hold outputs of functions, which I’m only going to pass to other functions. But there are advantages and disadvantages to declarative, strongly typed systems, and I knew about this already, so I can’t really complain. Then the final straw: there are no list, tuple, or map types. You think I should use the STL? You’re right — that’s precisely what I ought to do.

Except: the STL requires layer upon layer of confusing boilerplate, and in order to navigate it, you have to really know your C++ shit inside and out. Today, I wanted to remove some unwanted elements from a vector. Several StackOverflow question-reads later, I think the best route is to create a functor (loosely, an object wrapping a function) to use with an iterator to pass into a function to pass into another function. After all that, I have little knowledge of the big-O algorithms underlying these pieces of my code. I’ve also written a dozen lines for what I think of as ‘l.remove(e)’, and I’m wading through complex STL errors to figure out simple syntactical issues.

Worst of all: it doesn’t even work yet. ‘std::remove’ will remove elements equal to a given value, but doesn’t handle functors, while ‘std::remove_if’ can handle a functor, but messes up my iterator somehow so the vector doesn’t truncate.

Imagine a compilable and interpretable dynamically-typed (or at least type-inferred) language with minimal syntax and useful built-in types possessing relevant comprehensions. Now, imagine that it has bindings to popular open source game development libraries. Why can’t that be a thing?

I’m sure that 90%+ of my issues are coming from not having a sufficiently well-developed mental model of the C++ landscape, and if I knew my way around, I wouldn’t be having these problems, but I don’t. I didn’t expect to have to learn how to walk again when I’m already intimately familiar with C, with Python, and with reasonable program design. It’s not a different paradigm, it’s just that everything is harder here.

A different take on the situation is that the things that I’m annoyed by are showing me weaknesses in my own comprehension. Details I ought to be comfortable with are so commonly swept under the rug that I’ve forgotten they were even there, and now that I have to think about them, I’m more prepared to whine than solve the problems. So I’ll just keep on with it, I suppose, but there may yet be more whining.