3

I cloned my entire GitHub repository to a local computer using:

git clone git@github.com:my_account_name/my_repository_name.git

Suppose the branches I had on the remote repository were foo and bar. When I do:

git branch -r

the remote branches stored on my local computer are listed with the names:

origin/foo
origin/bar

(And with git branch -a, they appear with remotes/ further prefixed.) When I work on the branches on my local computer, I want to refer to the branches without the origin/ prefix. For each branch, I can probably do like:

git branch -m origin/foo foo

to rename the branch, but I actually have a lot of branches, and do not want to do it manually one by one. Is there a way to get rid of these origin/ (or remotes/origin/) prefix for multiple remote branches on the local computer at once?

sawa
  • 165,429
  • 45
  • 277
  • 381

4 Answers4

3

Just do git checkout foo. That's it.

You're not supposed to rename or work in the origin/* branches, they track the remote repository's state. You don't work in them directly, you create your local copies.

Checking out a branch which doesn't exist locally but does exist remotely creates this branch automatically for you, so just do a checkout but omit the origin/ part.

tkausl
  • 13,686
  • 2
  • 33
  • 50
  • Is there a way to checkout all of them (one after another) at once to just create a local branch for each of them? – sawa Oct 27 '17 at 06:02
  • 1
    Is [this](https://stackoverflow.com/questions/379081/track-all-remote-git-branches-as-local-branches) what you're looking for? – tkausl Oct 27 '17 at 06:03
  • 1
    @sawa: you can use the linked answer to do that; but in general you *shouldn't*; it does not make things any easier for you now, and eventually makes things harder for you because now you have a whole slew of local branches you constantly have to update or prune. Better to let `git fetch` update your remote-tracking branches automatically, and make local copies only when you start working on them. – torek Oct 27 '17 at 06:09
  • I got a feeling that `git clone --mirror` suggested in an answer to the link provided by @tkausl is (close to) what I was looking for. – sawa Oct 27 '17 at 06:14
  • This does not work for the branches I have not created locally. I cannot checkout the branches without the origin/ prefix and I am getting pathspec does not match any known files. Using origin/ as prefix works fine, but keeps the prefix in the branch name. git version 2.21.0.windows.1 – Radu C Jul 30 '19 at 14:27
2

The short answer is "no, and you should not even try".

A remote-tracking branch name is not a branch, despite the name "remote-tracking branch name". Instead, it's your Git's memory of some other Git's branch name. This serves several purposes, including the ability to create your own branch names from these remote-tracking names.

In Git, a branch or tag name, like master or v1.1, is a device Git provides to let you assign a human-readable name to a (one, single) hash ID. These hash IDs are usually the IDs of commits. (The normal exception occurs with tags, which can name tag objects, which then name commits; this is how Git implements annotated tags.)

What makes (local) branch names special is that they have the unique property that you can "get on them", by running git checkout with a branch name. Once you do, git status will say things like on branch master. And—this is the really special trick—if you now make a new commit, Git will automatically store the new commit's hash ID in the current branch name, i.e., the one you're "on".

As another special trick, if you tell Git to get on to some branch name B, and branch name B currently does not exist, Git will scan your set of remote-tracking names, such as origin/master and origin/B. If it finds exactly one such name, it will:

  • create a new name B
  • pointing to the same commit as origin/B
  • and set to track origin/B

(these term are especially unfortunate: a local branch name "tracks" a "remote-tracking" branch name, which is named according to the remote, and yet every single one of these things is local!).

Every time you run git fetch origin, your Git calls up another Git, at the URL associated with the remote named origin. The other Git tells your Git what branch names it has right now, and what commit IDs go with those names. Your Git downloads any new commits and, at this time, updates your remote-tracking names to match their names, updating your Git's memory of what is in their Git over there. So even if you do manage to do something with the remote-tracking names, you'll wipe out all your efforts on every git fetch.

Note that once you have a branch named B, it's totally independent of what happens to your origin/B, until and unless you instruct your Git to do something to re-synchronize with your origin/B. You might do this after you git fetch, to first synchronize origin/B with the Git at origin, then to synchronize your B with your origin/B.

(Git provides the two-step "synchronize, then synchronize again" as a convenience command, git pull, but for anyone starting with Git, I recommend avoiding this command—it does too much, sometimes poorly; and when something fails, it leaves you in a mess you can't recover from because you don't know which step failed and cannot read the correct documentation, which is specific to that step!)

torek
  • 448,244
  • 59
  • 642
  • 775
  • A good essay illustrating the last point is ["Git: fetch and merge, don't pull"](https://longair.net/blog/2009/04/16/git-fetch-and-merge/). – kostix Oct 27 '17 at 08:42
1

They are remote branches. They need the origin/ prefix, it tells the remote repo where they belong to.

On the local repo you need to create local branches to track the remote branches. There are several ways to do it:

git branch foo origin/foo

creates the local branch foo that points to the commit pointed by the remote branch origin/foo (the branch foo on the remote repo origin).

If you want to start working on foo then you have to git checkout foo. But you can combine both commands in only one:

git checkout -b foo

If there is only one remote branch named foo, git checkout identifies it (it's origin/foo) and internally runs the equivalent of the first two commands listed above.

If you don't need all remote branches you can remove (one by one) them using:

git remote -d -r origin/foo

-d is "delete", -r tells it that the branch is a remote branch.

You can remove more than one branch at a time but it doesn't accept wildcards. You can, however, combine git branch --list with grep to get the names of the branches to delete:

git branch -r --format '%(refname:lstrip=2)' | grep 'foo*' | xargs git remote -d -r

Replace 'foo*' with any wildcard you need to match the desired branch names.


Read more about git branch, git checkout, grep and xargs.

axiac
  • 68,258
  • 9
  • 99
  • 134
0

You can rename your brach during checkout and use alias like this:

cb = !sh -c 'git checkout -b $1 origin/$1' -

After that you will be able run commands like:

git cb foo
git cb bar
cn007b
  • 16,596
  • 7
  • 59
  • 74