Git Using Remote Branch
Posted By: Anonymous
If I have cloned a git repository, I only have the master branch on my local machine. If the actual repo has a branch I’d like to work on, say alpha, how exactly do I work on that branch locally then push to create a PR for that branch?
I’ve heard that maybe I need to do:
git switch alpha (which creates the same branch on the repo on my local machine). Or do I need to do git switch origin/alpha
Then when I’m in that branch and make changes, how do I push to that branch then make a PR on github?
Solution
If I have cloned a git repository, I only have the master branch on my local machine.
Branches—or more precisely, branch names—exist to find commits. They are not the only way to find commits, though.
When you first clone (i.e., copy-via-Git) some existing Git repository, you get all of the other Git repository’s commits,1 but none of their branches. That state exists for a few nanoseconds or milliseconds or so, and then git clone
creates one branch name in your copy.2 Typically that’s master
or main
, depending on the other Git (see footnote 2). Since you mentioned master
, let’s go with that one.
So: if the other repository, the one you’ve copied, had, say, six branch names … what happened to the other five? Well, the answer is: the same thing that happened to their master
. Your Git renamed all their branches. Your Git changed them all into remote-tracking names by sticking origin/
in front of each name.3 So their six branches became six remote-tracking names in your Git repository.
Your Git then created a new master
in your own repository, just so that you could have a branch to be on. Your own master
now selects the same commit as their master
, which is your origin/master
.
If the actual repo has a branch I’d like to work on, say alpha, how exactly do I work on that branch locally then push to create a PR for that branch?
Use any command to create the name. The "best" command is probably git switch
(since Git 2.23). Both git switch
—the new, not quite so super-powered command that is safer to use than git checkout
4—and the old git checkout
have what Git calls DWIM mode, where if you ask to get on a branch that does not (yet) exist, Git will look to see if there’s some remote-tracking name that’s otherwise identical. So if there is an origin/alpha
and you run git switch alpha
, your Git will create your own alpha
, pointing to the same commit as your origin/alpha
, which is of course the same commit that their Git has—or had at the time of cloning—as the last commit in their alpha
. (Whew!)
Generally, you’ll want your alpha
to identify this same last commit as theirs. If your Git repository could be out of date—if you think they may have added new commits since your git clone
—you should probably run git fetch
first. The fetch
command has your Git call up their Git, list out their branch names, and then get any new commits they have, that you don’t yet, and then update your remote-tracking names.
When you ran git clone
, your git clone
essentially used git fetch
to get all their commits, initially. The code is built into git clone
, so it doesn’t literally run git fetch
, but it’s the same code: your Git created an empty (no-commits) repository, then ran git fetch
against their Git. All their commits were new-to-you so your Git got all their commits. Then your Git created or updated any remote-tracking names based on their branch names. All their branch names were new-to-you, so your Git created all the remote-tracking names.
A new git fetch
calls up their Git, gets any new commits—you already have the existing ones—and creates or updates your remote-tracking names again. That’s all it does, so it’s safe to run at any time. It does not check out any of their commits. It does not add their commits to your branches. It just gets new commits, if any, from them, and updates your remote-tracking names.
Anyway, once you have your own branch name, you can start adding your own commits. Every commit gets a unique hash ID, so your new commits will have a different hash ID from every commit—even any new ones they make while you’re making new commits of your own—and your Git and their Git will be able to tell these apart, just by their hash IDs. (That’s why these hash IDs are so big and ugly: so that they can be unique.)
When your commits are ready for review or whatever other process you will use, you can send your commits to the other Git repository. You’ll have to have them—the other Git—set one of their names to remember your new commits, though. Typically you’ll set a branch name in their Git repository. That might be a new name, or might be alpha
. You might then create a "pull request", which is a fancy GitHub thing (there’s a slightly different fancy Bitbucket thing, and a slightly different from both of those fancy GitLab thing, all called "pull requests"). All of these details depend on (a) what other Git repository you’re using and (b) the standard work-flow that everyone in your group uses, so it’s a little early to get into specifics here. The only thing we can say with some (but not complete) certainty is that you’ll probably send your commits using git push
, which is as close as Git gets to the opposite of git fetch
.5
1It’s possible to get less than every commit, for various reasons and using various methods, but let’s just go with this as the initial view of cloning.
2If you don’t want git clone
to create one branch, use git clone --no-checkout
. If you want to control the name of the branch, use git clone -b
. Note that if you provide a tag name to -b
, the last step of git checkout
will not actually create a branch name either.
If you use neither --no-checkout
nor -b
, your Git asks the other Git what branch name they recommend, and pretends you supplied that name as your -b
option.
3The remote-tracking names actually live in a separate name space, under refs/remotes/
, and the origin/
part assumes that you are using the standard first remote name. You can choose some other name with the -o
option to git clone
, though you probably should not, since all the introductory Git reading material you’ll find will assume origin
here.
4It’s safer in the sense that, say, a hand sanding block is safer than a power sander: you won’t accidentally grind your knuckles right off with a hand sander. 🙂 More seriously, the old git checkout
command has a safe mode, git checkout <em>branch</em>
, and an unsafe "please wreck all my unsaved work" mode, git checkout <em>file</em>
. It’s really easy to accidentally invoke the file
version when you meant to invoke the safe branch
version. The git switch
command is different enough, and lacks the unsafe mode—that’s in the new git restore
command instead—that it won’t destroy unsaved work like this. You can still destroy unsaved work, but you have to work harder to make that happen.
5The somewhat mis-named git pull
means run git fetch
, then run a second Git command. The default second Git command is git merge
. This is very different from git push
because git push
does not have a second step and never does any merging. That’s why fetch
is as close as we get to the opposite of push
: neither does any merging.
Answered By: Anonymous
Disclaimer: This content is shared under creative common license cc-by-sa 3.0. It is generated from StackExchange Website Network.