About Push, Pull, Merge, Etc
This is a lightly edited IRC log of a discussion about how push/pull/merge/update/etc work. The user had two branches, one on a Linux box, the other on a Windows box, and this is about how the commands are used to move stuff among them.
This discussion was continued about another topic in AboutUsingRepositories.
This should be cleaned up into an actual document some time, but for now, it's here for reference.
Log
- fullermd
- Try this. The important unit is the Revision; a given state that you commit'd (there are other ways to create them, but that's 99.99% of them)
- fullermd
- So everything you do is in some way related to manipulating revisions (rather, moving them around, since they're immutable once created)
- USER
- yeh, your only creating new revisions by branching the previousrevision. that makes sense,
- fullermd
- The three bits you work with are Repositories, Branches, and Working Trees. And most of the time you don't actually work with Repositories, so you can pretend they're just a part of the Branch.
- fullermd
- So you can think of the Repo/Branch as SVN's repo, and the Working Tree as a SVN checkout.
- fullermd
- (except of course that on a SVN project, you need to move heaven and earth to have multiple repos talking together. And even then it's iffy.)
- fullermd
- So, you have two Branches (and their associated Repos); one on the Linux box, and one on the Windows.
- fullermd
- And each branch has a Working Tree.
- fullermd
- So the question you need to answer at any given point is "What am I doing with the Revisions?"
- fullermd
- The answer can be "making a new one", which basically means editing files in the WT, fixing old bugs and creating new ones, and then 'commit'ing them to make a new Rev.
- fullermd
- Once that's done, you have a new Rev in that Branch (and _not_ in the other Branch, so they're now out of sync, even if they were perfectly sync'd before)
- fullermd
- The other main answer is "copying Revs from one of these Branches to the other"
- fullermd
- That can happen via a variety of commands, the most pertinent being merge, push, and pull. Each of those applies in a slightly different situation.
- fullermd
- push and pull are (almost) symmetrical, it just being a question of whether you're in the source pointing at the destination, or in the destination pointed at the source.
- fullermd
- Either of them works in the case that your source already includes everything the destination does (and presumably has new stuff on top)
- fullermd
- e.g., you commit on the Windows Branch, then you 'push' that new rev to the Linux Branch. Or you commit in the Linux Branch, and then you go into the Windows Branch and 'pull' that new one down.
- fullermd
- Clear so far?
- USER
- so from your own perspective, you can treat one working copy as a master repo like i am doing, pretty successfullyl.
- USER
- yeh, so far it's making sense.
- fullermd
- OK. So that just leaves us with 'merge'.
- USER
- yeh, this is the fuzzy one.
- fullermd
- Merge is what you use when you can neither push nor pull (simplifying things).
- fullermd
- Which is to say, that _neither_ branch is an "old version" (so to speak) of the other.
- fullermd
- Say you commit on Windows, and then you go commit something else on Linux.
- fullermd
- Now _each_ branch has stuff the other doesn't. So you can't pull/push either way (without losing stuff).
- USER
- when there are parallel changes in both branches, the local windows one and the linux one it pulled from.
- fullermd
- Right. So now we need a way of pulling these two heads together. Or, should we say, merging them.
- USER
- aha, ok that's making a little more sense.
- fullermd
- Since accessin Win remotely has its issues, we'll just assume you're sitting at the Win box when you go to resolve this.
- USER
- yeh, ok
- fullermd
So you'd do a "bzr merge bzr+ssh://linux/foo" (or whatever the path; it will default to the same location as 'pull' if you don't explicitly give one, so you probably don't need to give one at all)
- USER
yeh, i don't have to.
- fullermd
- What that would do, is bring over that Rev (or Revs, if there are more than one you don't have locally), merge the changes in the Working Tree, and stash the actual Revs in limbo.
- fullermd
- That gives you a chance to review the changes made, fix any conflicts, and then when you're satisfied with the merge, commit it.
- fullermd
- What that gives you now is a new Rev, which has _two_ parents, instead of the _one_ that you normally have.
- fullermd
- To wit; your previous local head Rev, and that head Rev you got from the other branch.
- fullermd
- So NOW, this local branch is a superset of the remote branch, and you can 'push' without losing anything.
- USER
- ok, that's pretty well explained,
- fullermd
- OK.
- fullermd
- So since update was brought up, let's skim that real quick
- USER
- ok
- fullermd
- Update is most useful when your Working Tree is out of date with your Branch.
- fullermd
- That will happen in this scenario when you've made changes on Windows (whether purely local or involving merge's, doesn't matter), then you 'push' them to the Linux box.
- fullermd
- Over remote protocols, push doesn't update the working tree.
- fullermd
- So now your WT on Linux considers itself "based on" an older revision, which is no longer the head of the branch.
- fullermd
- And you can't commit from that state; you can only add on to the 'end'.
- fullermd
- So you'd need to "bzr update" on Linux to 'catch up' the WT with the branch.
- fullermd
- When you 'pull', you generally do it from within a branch, so 'pull' will update the WT as a matter of course after it does the Branch changes.
- USER
- so if i did a bzr commit on the linux WT at that point, before doing update, it would complain?
- fullermd
- Right. Also, I think 'status' warns when the WT is pointing at an older rev.
- USER
- ah, ok
- fullermd
- Pretty much what happens with SVN if you try and change a file after somebody else commit'd to it, but without update'ing.
- USER
- yeh, ok
- fullermd
- It just happens less often in bzr, since Most Of The Time(tm), people aren't push'ing revs into your branch behind your back.
- USER
- :P
- fullermd
- The only way you get new revs is by commit'ing them, or pull/merge'ing them from elsewhere.
- USER
- sneaky commit's
- fullermd
- But in some cases, like this one, you have a branch that is both "a branch you're working in", and "a branch you're pushing into from elsewhere" [the Linux one], so new revs can show up without the WT knowing about it.
- fullermd
- And there's nothing at all wrong with that. It just means you sometimes have to nudge the WT.
- USER
- huh, that goes along way to explaining how you can merge copies of code from various different members of a team.. it is a bit more of a learning curve than svn... but i can see some plausible use cases
- fullermd
... I think that's sufficient confusion