2

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?

Weafs.py
  • 22,731
  • 9
  • 56
  • 78
MinusFour
  • 13,913
  • 3
  • 30
  • 39
  • 1
    You have it the other way around. `git rebase origin/master` rebases your commits on top of `origin/master`. – jcm Aug 30 '14 at 02:56
  • Do you mean that it copies origin/master into my local master branch and then add the new commits? – MinusFour Aug 30 '14 at 03:27
  • Something like that. You may have seen them already but I find the [official docs](ftp://www.kernel.org/pub/software/scm/git/docs/git-rebase.html) helpful. – jcm Aug 30 '14 at 03:53

1 Answers1

6

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:

  • to locate commits within the commit graph, and
  • only if applicable: to move the branch so that it points to the correct commit

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 HEAD2 (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.

torek
  • 448,244
  • 59
  • 642
  • 775
  • +1, partly for noting the difference between branches and commits, partly for pretty ASCII commit graphs, mostly for git assimilation – Jason Baker Aug 30 '14 at 02:45
  • Thank you for the explanation! Could you elaborate on: "After making the copies, git rebase adjusts your branch master to point to the new tip-most commit." Isn't there nothing on the local branch master after the rebase? Aren't the commits moved to the tip of the newly fetched origin/master? – MinusFour Aug 30 '14 at 03:11
  • @MinusFour: you might look at some of my other answers, e.g., http://stackoverflow.com/a/25222144/1256452, where I show the old "abandoned" commits being still in the repo, and recoverable as long as you can find a way to name them. Also, look for answers where I talk about how branches "automatically move forward", e.g., http://stackoverflow.com/a/21055585/1256452 ... in this case you're not "on" `origin/master` (you can't be) so it *does not* move. – torek Aug 30 '14 at 03:27
  • I think I understand now. The tutorial made me think rebase actually destroyed my master branch to move it out to origin/master. Now I'm thinking it just updates the reference to newer commits that also links the origin/master commit graph. master now includes the new commits plus whatever was in origin/master. – MinusFour Aug 30 '14 at 05:23
  • @MinusFour: yes, that's exactly right. The original commits are still there, and their contents have been copied to new commits (almost the same, just different enough to be rebased) and `master` points to the tip-most of these new copies. – torek Aug 30 '14 at 05:27