gg-scm/gg

pull/clone should create & update local branches for any remote branches

zombiezen opened this issue · 3 comments

To make gg update and other commands that would want to use remote branches work regularly, I want gg pull and gg clone to create local branches (refs/heads/foo) for any remote branch (refs/remotes/origin/foo) with the upstream pointing to the remote branch. If multiple remotes have the same branch name, the one for the "origin" remote wins, otherwise the branch is not created. After a successful pull, for every existing local branch that has an upstream pointing to the pulled remote and no diverging commits will be fast-forwarded. This includes the branch pointed to by HEAD: if this is the case, then the working copy will be placed in detached HEAD state at the same commit.

After more thinking about this, I don't like the behavior I described initially. Detaching HEAD makes Git lose track of the branch it's on and making "origin" special feels wrong. Let me try again:

For every branch in the remote, check for a local branch with the same name. If it exists:

  1. If HEAD points to the local branch, do nothing. (The next gg update will move the branch forward.)
  2. If the branch can be fast-forwarded to the remote branch, do so.

If the branch does not exist locally, create it at the same commit as the remote branch with the local branch's upstream pointing to the remote branch.

I'm liking the direction this is heading, because it removes the special-ness of FETCH_HEAD and makes random URLs more easily pull-able. One snag, though: the not-updating-HEAD element poses a trick for pulling an argument that isn't a remote, since there won't be any tracking branch patterns configured.

I propose that in the case where the pull target is not a named remote, the fetched branch refs are written to a new ref hierarchy: refs/ggpull/BRANCHNAME. This way, the local branch updating can be cleanly separated from the remote fetching, and the logic will mostly remain the same.

Work remaining: document new behavior and fix gg pull -u behavior in cases where changes are being pulled from not-the-upstream.