Hacker News new | past | comments | ask | show | jobs | submit login

... that is not simple. But I'm figuring it out anyways.

I commit my changes to my own repo and keep building changes under HEAD, committing as I go. If I get a branch from a buddy and I want to add it to my code, I either merge or rebase depending how I want his commits to be intertwingled.

Because GIT is decentralized, there's no difference between merging in a buddy's branch, and import the latest changes from Origin into my branch. So I fetch the changes from origin/master and then rebase or merge my repo on top of that. That's my "Get Latest" command, basically, right? Assuming I'm working on "master", I fetch then rebase or merge origin/master.

To check in, I tell the origin server to take my stuff and then rebase or merge its master with that.

I still feel like this is a rather baroque approach to the problem... managing oodles of local commits separate from rebase/merges seems bizarre, above and beyond the decentralized approach that makes my own repo, my peer, and the "origin's" stuff all equivalent.

The decision of when to merge vs. rebase is still confusing to me.




> The decision of when to merge vs. rebase is still confusing to me.

I'll take a stab at this. When you merge, you're merging their branch into yours. At the end of you have both pieces of code, but all the history is still there. You can see that their branch started 20 commits ago, that two things were done in parallel, and that they came back together with the merge.

Rebase is a different. Rebase changes history. Rebase is like this:

    1. Find the common ancestor between the branches
    2. Extract each commit from their branch, turn it into a patch (named patch*N*)
    3. Switch back to your branch
    4. Apply patch1, patch2, ... patch*N* in order
Now it looks like all the work was done at the end of your brach, like it was based on your latest commit. Instead of being based on the common ancestor commit, it is now based on your commit. It's been rebased.

It makes sense if you think about Git coming from kernel development. Developers tended to work in patch sets, a long series of patches to a common base. Rebaseing is just applying that series of patches to a different base.

Merging merges branches, but rebase is more like moving branches.


One small point: on check-in, I don't think it's exactly that origin is also rebasing/merging just like you did. It's more like origin is just taking whatever you have and copying it exactly. The merging/rebasing process itself only happens locally.

Regarding merge vs. rebase, here's my approach: rebase to keep history a straight line when it's just your changes and it's just a few commits. If it's too many commits you tend to have more conflicts and it's usually easier to merge.


> One small point: on check-in, I don't think it's exactly that origin is also rebasing/merging just like you did. It's more like origin is just taking whatever you have and copying it exactly. The merging/rebasing process itself only happens locally.

But then what happens when I merge/rebase locally and publish at the same time as somebody else? I assume the origin doesn't keep a lock on the whole mess while I'm doing my local merge/rebase. That sounds like it would lead to a "last-one-wins" conflict-resolution or a complete reversion of the origin if I publish without rebasing on the origin's version first.


> I assume the origin doesn't keep a lock on the whole mess while I'm doing my local merge/rebase.

You're right that the remote server has no idea what you're doing on your local machine.

> . That sounds like it would lead to a "last-one-wins" conflict-resolution or a complete reversion of the origin if I publish without rebasing on the origin's version first.

Unless you use a --force option, Git will refuse to do anything that will lose information. When the second person pushes, Git will say "You can't get here (new commit) from there (their commit). Nope." In that case it's up to you to pull their changes and either merge or rebase your changes. At that point when you push your new commit will be a descendent of the server's latest copy, and it willy happily accept it.

Now Git's messages aren't that friendly. The message you'll get is something like 'Unable to perform a fast-foward merge'.


Are you using gitflow? https://github.com/nvie/gitflow

So yes, if you try to push without pulling down changes, then you will get an error about the histories having diverged. Sometimes you don't care about wiping out history, and can just push with the -f parameter, but most of the time that's your cue to rebase.

Branches are cheap in git, and there's no real advantage to doing dev work in the master branch. You should create a branch at least as often as you develop a new feature. In git, history isn't necessarily a static thing. Sometimes you need to mangle it to achieve your goals, and sometimes you fat-finger the merge and do time in History Hell. In either case it's only a huge flaming deal if you're working on master. Ditto with the problem you describe.

I recommend the O'Reilly book on Git. The simple explanations are nice in theory, but this is a complicated subject and deserves a full explanation. There are very sound reasons for the how and why of git, and they should be within the grasp of any aspiring programmer.


I'm not using git at all, I'm trying to understand how it works before I start. Every guide to git I read before was a completely opaque mess of terminology, so this is the first time it's starting to make a lick of sense.


I think Git is much easier to understand if you understand the underlying data model. The core object in Git (as far as you need to care) is a commit. Each commit holds a link to the commit(s) it was based on. If two commits have the same parent, you have two branches. If one commit has two parents, it's a merge. Individual commits don't know what branch(es) they are a part of.

Branches are just pointers to commits. When you make a new commit on a branch, the new commit is saved and the branch pointer is moved forward to point to the new commit.

Tags point to branches, but they don't get updated. They're supposed to be permanent (but can be modified if you try). If a tag points at a commit and you make a new commit, the tag still points to the original commit.

The only other odd term would be HEAD, which is like a branch that ALWAYS points at what you have checked out at the moment. You'll see this if you make commits without being on a branch (say you checked out an old commit and just started working).

Since branches are just pointers at commits, you can move them around easily. If you make 6 new branches, they all just point at the same commit to start, which is why it's so amazingly fast to do. If you want to undo a commit (that you haven't pushed), you can move the branch pointer to a previous commit. After that when you make new commits it will be like the mistake never existed. (Note: If you accidentally do this, it can be fixed if you catch it soon enough).

When it comes to using branches, "A Successful Git Branching Model" [1] is very commonly used, and works fantastically. I had almost no trouble getting the other developers in my company on the model, and it makes it very easy to keep things straight.

If you'd like help understanding Git, I'd be glad to try to help you. My email address should be in my profile. You may find this kind of thing much simpler if you look at the graph of repository. My company uses SourceTree[2], which is a pretty great GUI and makes it easy for me to see how the various branches I've got relate.

[1] http://nvie.com/git-model/ [2] http://www.sourcetreeapp.com (Mac & Windows, Git has a basic gui command built in if you want)


> Tags point to branches, but they don't get updated.

Did you mean to say tags point to a commit?


Yep, good catch.


It notices that origin has commits that you don't have and rejects your push. Then you pull the change that happened in the meantime, merge/rebase your change again on top of that, and push again.

If we're recommending books on Git, I recommend Pro Git. It's free online. http://git-scm.com/book


> The decision of when to merge vs. rebase is still confusing to me.

i always thought it was "never rebase commits you have pushed" at least you know about rebase though. :)


That is certainly the rule 99.99999% of the time. It's possible, but it can be a mess for everyone else.

Before you push, you can choose to do it either way.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: