I'm new to git, I've been following this tutorial.
I think I understand most of it, until I got to remote repositories. The only concept about remote repositories I understood is git fetch and git remote. According to that tutorial, git fetch gets the remote repository from the specified url by the add option of git remote. It downloads the repository into a "remote" branch. If I understood correctly, it isn't a branch in a remote repository but the branch I downloaded from the remote repository. It isn't part of my local repository just yet, it's still there to be merged/rebased into it (my local repository). Maybe I'm wrong and I'm missing something here, please feel free to correct me.
Now, what I feel I don't understand at all is how does git manage to rebase the "remote" repository into my local repository.
I understand that when I rebase a branch, it will base the commits in that branch to a different commit of where it originally branched off. I still have to merge the branch into my master branch. What actually happens when I do?
git checkout master
git fetch origin
git rebase origin/master
Wouldn't this rebase my local master branch into the remote master branch? I keep thinking of this picture.
Instead of feature I would have my local master branch and instead of Master, I would have the remote origin/master Branch. With the exception that Master doesn't really branches out origin/master.
Wouldn't this remove my local branch master? Wouldn't this move all my work into the "remote" repository? Also, I don't need to merge back before pushing it to the real remote repository?
The key here is that the rebase, like most1 other branch-related items in git, really works off the commit graph and not the branch names. The branch names are used for one or two purposes:
So if you run:
git checkout master
git fetch origin
git rebase origin/master
the first step gets you "on branch master": it simply writes master
into HEAD
2 (and of course updates your work tree).
The second step grabs any commits from origin
that you don't have yet. These go into your repository, augmenting the commit graph, and updating origin/master
to point to the newest commit there. For instance, you might have had this before the fetch
:
* - * <-- HEAD=master
/
..- o - o <-- origin/master
Once the fetch
is done, and your git-borg has added origin
's biological and technological distinctiveness to its own, you now have:
* - * <-- HEAD=master
/
..- o - o - o <-- origin/master
At this point, you can git rebase
your two commits (the filled in *
s) on to the tip of the new origin/master
. This actually works by making copies of your commits: you get two new ones, that do the same as the old ones, but have different parent-IDs: they chain off the new tip of origin/master
instead of off the old (pre-fetch
) tip. After making the copies, git rebase
adjusts your branch master
to point to the new tip-most commit.
(And, in keeping with the Borg theme, your original commits are still in your repository. They do eventually get discarded, once the reflog entries expire, in 30 days by default.)
1The exception here is things that do branch name things only. For instance, you can make one branch an indirect reference to another branch. Normally this is only done for HEAD
though. Or, you can rename a branch, which doesn't really have anything to do with where it points.
2More precisely, it writes ref: refs/heads/master
into .git/HEAD
. That's what it takes to be "on a branch": the full name of the branch goes in that file, plus the "ref:(space)" prefix.