{"thread":{"id":"1913","subject":"Re: Please undo \"Use git-merge instead of git-resolve in","startedAt":"2005-09-22T14:55:26Z","lastAt":"2005-09-22T16:06:09Z","messageCount":3,"participants":["Jon Loeliger","Petr Baudis","Linus Torvalds"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"9117","messageId":"E1EISTu-0000MI-Gz@jdl.com","threadId":"1913","inReplyTo":null,"subject":"Re: Please undo \"Use git-merge instead of git-resolve in","fromName":"Jon Loeliger","fromEmail":"jdl@freescale.com","sentAt":"2005-09-22T14:55:26Z","receivedAt":"2005-09-22T14:55:26Z","isPatch":false,"sender":{"key":"jdl@jdl.com","avatar":"https://gravatar.com/avatar/75ce9a10b151acd2c28ec4ab2136dba7b2ff1634530bd04b155981a749d08a64?d=mp&s=160"},"body":"Dave Wrote:\n> From: Linus Torvalds <torvalds@osdl.org>\n> \n> > I often have local changes in my tree that I don't want to commit but that \n> > I'm testing out. Havign them interfere with merging other peoples work \n> > would mean that I'd have to have a totally separate tree for that, which I \n> > could do, but I'm much much happier not having to.\n> \n> You know, I personally was unaware that this was supported until now.\n> I have been always reverting local debugging changes in order to merge\n> other people's work in, then reapply the debugging changes afterwards.\n\nSo, interesting that this comes up now, as I recently had a\ndiscussion on this topic with a few coworkers.  We concluded\nthat we were clueless and what would help us out a whole bunch\nwould be a few more Use Cases down this line added to the Tutorial.\n\nI'll include my original (internal) question as an example\nuse case.  Perhaps it will illustrate two things:\n\n    - How clueless I am about Git still\n    - Where some of the Git Frustration still lies\n\nI'd offer to write it, but I'm just flat in the dark here and\nneed to _read_ it first. :-)  I'll offer this instead:  If you\n(someone) tells me the commands that illustrate how to do what\nI'm after here, I'll make a stab at writing up the tutorial\nUse Case for it.\n\n(Yes, I know there is a Use Case very similar to this in\nthe Tutorial, but it is not quite the same.  And I can't\nsee how to intuit a step towards what I'm wanting here.)\n\nThanks,\njdl\n\n\n\n    OK, so I have a git tree that looks like this:\n\n    241 % git show-branch --more=5\n    * [jdl] Merge with rsync://www.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git\n     ! [master] Merge branch 'master' of /home/src/linux-2.6/\n      ! [origin] Merge branch 'master' of /home/src/linux-2.6/\n       ! [paul] Merge with rsync://www.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git\n    ----\n    +  + [jdl] Merge with rsync://www.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git\n    ++++ [master] Merge branch 'master' of /home/src/linux-2.6/\n    ++++ [master~1] NTFS: Fix ntfs_{read,write}page() to cope with concurrent truncates better.\n    ++++ [master~2] NTFS: Fix handling of compressed directories that I broke in earlier changeset.\n    ++++ [master~3] NTFS: Fix various bugs in the runlist merging code.  (Based on libntfs\n    ++++ [master~4] vc: Use correct size on buffer copy in vc_resize\n    +  + [jdl~1] Merge rsync://rsync.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc-merge\n    +  + [jdl^2] ppc32: Allow user to individual select CHRP/PMAC/PREP config\n    +  + [jdl^2~1] powerpc: Merge simplified sections.h into asm-powerpc\n    +  + [jdl^2~2] powerpc: Remove section free() and linker script bits\n    +  + [jdl^2~3] powerpc: Remove sections use from ppc64 and drivers\n    +  + [jdl^2~4] powerpc: Remove sections use from ppc\n    +  + [jdl^2~5] ppc32: Removed non-inlined versions of local_irq* functions\n    ++++ [jdl~2] Merge master.kernel.org:/home/rmk/linux-2.6-arm\n\n    I have current, modified, non-committed files in my working tree\n    in the \"jdl\" branch.  I don't want to commit them now (yet).\n\n    I now know that Linus has updated his tree with new -rc2 parts.\n    I want it.  In fact, I want it on the \"origin\" or \"master\" branch.\n    (Or both.  And I don't know which.)\n\n    How do I get Linus' updates and merge them into the \"origin\" branch\n    without changing to that branch first?\n\n    How do I get Paul's updates and merge them into the \"paul\" branch\n    without changing to that branch first?\n\n    I think I can fetch the Linus updates by doing something like this:\n\n\tgit fetch origin\n    or\n\tgit fetch rsync://....path/to/linus-2.6-git\n\n    That will just grab the Objects and throw them into my .git/objects.\n\n    But how to do the merge?  I think that the merges all require\n    the \"target branch\" to be the \"active\"/checkedout branch, right?\n    I don't know how to now say \"Merge-up those new Objects on the\n    origin branch\".\n\n    I think what's confusing me still is that the previous\n    World View According to CVS was essentially that you have\n    this import branch into which you dragged all the external\n    updates.  Then you merged that over to your working branch.\n    And, you could easily have views of _both_ of those\n    branches simultaneously.\n\n    With Git, you can't really do that in quite the same way.\n    Sure, you can treat a branch as an \"import branch\".  But\n    if you have uncommitted files over in a different branch,\n    you can't change your cehckout-view to do so.\n\n    However, I _could_ just stick in my \"jdl\" working branch and\n    directly pull-in and merge the linus changes.  I mean, my next\n    step after pulling those changes into the so-called import\n    branch was going to be to merge them to my branch anyway.\n\n    OK, so let's say I did pull linus' update into the jdl branch.\n    And they merge up nicely.  How do I now propogate _just_ the\n    linus changes to the origin branch?  Again, I don't think I\n    can without first checking out the \"origin\" branch.\n\n    Am I missing something here?  Fighting against the tool?\n\n\nA coworker replied:\n\n    > I read your message, and I read the git documentation, and I\n    > scratched my head a bit, and the end result is that I still don't\n    > know.  The docs really suck.  Everything you say seems to make\n    > sense, but I just can't confirm that it's actually how things\n    > work.  And I don't know how to do a merge like you propose.\n\nI responded:\n\n    So, you will all be pleased to know that I tried\n    some stuff and was not successful.  In the \"jdl\"\n    branch, I did a \"git pull linus\".  It happily went\n    out and grabbed all the new objects from his tree.\n    Spiffy.  It then announced that my branch of the\n    working tree was \"dirty\" and quit.\n\n    At this point, I _think_ this is where a \"cg-pull\"\n    instead of a \"git pull\" would have gone on, done\n    some figuring, and decided that it needed to\n    rebase my current changes after merging in the\n    fetched objects.\n\n    Not sure.\n"},{"id":"9125","messageId":"20050922160113.GL21019@pasky.or.cz","threadId":"1913","inReplyTo":"E1EISTu-0000MI-Gz@jdl.com","subject":"Re: Please undo \"Use git-merge instead of git-resolve in","fromName":"Petr Baudis","fromEmail":"pasky@suse.cz","sentAt":"2005-09-22T16:01:13Z","receivedAt":"2005-09-22T16:01:13Z","isPatch":false,"sender":{"key":"pasky@ucw.cz","avatar":"https://avatars.githubusercontent.com/u/18439?v=4"},"body":"Dear diary, on Thu, Sep 22, 2005 at 04:55:26PM CEST, I got a letter\nwhere Jon Loeliger <jdl@freescale.com> told me that...\n>     I now know that Linus has updated his tree with new -rc2 parts.\n>     I want it.  In fact, I want it on the \"origin\" or \"master\" branch.\n>     (Or both.  And I don't know which.)\n> \n>     How do I get Linus' updates and merge them into the \"origin\" branch\n>     without changing to that branch first?\n> \n>     I think I can fetch the Linus updates by doing something like this:\n> \n> \tgit fetch origin\n>     or\n> \tgit fetch rsync://....path/to/linus-2.6-git\n> \n>     That will just grab the Objects and throw them into my .git/objects.\n> \n>     But how to do the merge?  I think that the merges all require\n>     the \"target branch\" to be the \"active\"/checkedout branch, right?\n>     I don't know how to now say \"Merge-up those new Objects on the\n>     origin branch\".\n\n[I say 'master', but I mean the whatever branch you are currently\nworking on.]\n\nYour origin branch just represents what Linus has in his master branch.\nYou don't ever merge anything to it - if you fetch new stuff from Linus,\nit simply gets updated to point at the newest Linus' stuff. You can then\nmerge your 'origin' branch to your 'master' branch, therefore getting\nthe newest Linus' stuff there.\n\nAbout two nights ago I tried to describe all this branching stuff in\nCogito's README. It is aimed at Cogito, but generally appliable to GIT\nas well. s/cg-/git-/, cg-update is git-pull, and instead of using\ncg-branch-* you edit stuff in .git/remotes. It'd be interesting to know\nhow much more light it manages to shed on the issue, and generally what\ndo people think about it:\n\n\nUnderstanding GIT branching and merging\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nCogito's (inherited from GIT) concept of branching and merging may be a little\nconfusing at first, since it can be different from what you knew so far. First,\n\"branch\" is too abstract word for us, so we will abandon it for now. We will\npresent two other key concepts instead:\n\n\t- Repository - when you did `cg-clone` or `cg-init`, you created\n\t  a repository. That is a kind of container holding (usually) all your\n\t  history and data.\n\n\t- Head - each repository has some heads available. Those are kind of\n\t  handles for various sequences of commit. A head contains simply a\n\t  pointer to the last commit in the sequence, and if you commit 'onto'\n\t  a head, the pointer will be advanced to the new commit. Your\n\t  \"current\" head is the one you are currently working on. It is\n\t  normally called 'master'.\n\nNow let's take an hypothetical repository:\n\n\trepository\n\t+--------+\n\t|  master<  heads\n\t|   unoji<\n\t+--------+\n\nLet's suppose that we want to fork off master's development. We have two\npossibilities, either make new repository for it, or a new head.\n\nLet's say that we want to fork it off for our work offline on a notebook,\nso we will make it through cloning the repository to our notebook. What\nwill `cg-clone` do?\n\n\t+--------+\n\t+--------+\nFirst it creates an empty repository\n\n\t+--------+\n\t$  origin<\n\t+--------+\nThen it creates an 'origin' head, and will copy all the history from the\nremote repository's 'master' head there. So this head exists to reflect\nthe state of the remote repository. The important point is that it is\ncalled 'origin' in our new repository, even through it corresponds to\na 'master' head in the old repository. This is normal - you can name your\nlocal heads whatever you want.\n\nThe dollar sign denotes that this head is associated with a \"remote branch\"\n- a source location of the head is saved somewhere and you can fetch the\nhead and possibly push to it.\n\n\t+--------+\n\t|  master<\n\t$  origin<\n\t+--------+\nFinally it copied over the 'origin' head to the 'master' head, which will\nfrom now as your current head represent your local development in the\nrepository.\n\nSo you do some local development, do few commits on the 'master' head and\nwant to catch up with the upstream repository. You use 'cg-update', but what\nwill it do?\n\n\t+--------+\n\t|  master<\n\t$  origin< < < < <\n\t+--------+\nFirst, it will populate your 'origin' head with the new commits from the\nremote's 'master' head.\n\n\t+--------+\n\t|  master<-M-.\n\t$  origin>---'\n\t+--------+\nThen, it will merge those new commits to your 'master' head.\n\nNow let's imagine that there is also another head 'unoji' on the other side\nbesides 'master', containing some cool commits not in 'master' (it has such an\nexotic name, after all...). You want to merge its commits to your head too?\n\n\t$ cg-branch-add r-unoji 'http://remote/repository#unoji'\n\t$ cg-fetch r-unoji\n\nwill make your repository look like\n\n\t+--------+\n\t|  master<\n\t$  origin<\n\t$ r-unoji<\n\t+--------+\n\nwith 'r-unoji' containing stuff from the remote's 'unoji' branch.\n\nOk, you did some development, but you decided not to merge it into upstream's\n'master' yet since it is not yet stable enough. However, you want to upload it\ninto the upstream repository since it is public and you want people to be able\nto try out your stuff. Easy, let's push it to a new head on the server.\n\n\t$ cg-branch-add upmirror 'git+ssh://remote/repository#nislu'\n\nwill make your repository look like:\n\n\t+--------+\n\t|  master<\n\t$  origin<\n\t$ r-unoji<\n\t$upmirror|\n\t+--------+\n\nNote that 'upmirror' has no head associated, it has just the \"remote branch\"\ninfo. That is because it needs no head since it's solely for pushing. It is\nhowever normal to have a head (frequently it's the 'origin') both for pulling\nand pushing.\n\n\t$ cg-push upmirror\n\nwill then make the remote repository look like:\n\n\t+--------+\n\t|  master<\n\t|   unoji<\n\t|   nislu<\n\t+--------+\n\nwith 'nislu' on the remote side corresponding to the 'master' in your local\nrepository.\n\nOk, so this is how it goes for multiple repositories, where the cloned\nrepositories are essentially single branches. Note that if you clone the\nrepository locally, it can be actually very cheap, basically for free with\n`cg-clone -l` (but please read its documentation).\n\nBut what if you still do not want multiple repositories? The key here is to\nchange your \"current head\" from 'master' to some new head, and then to be\nable to switch back and forth. This is unfortunately something Cogito does\nnot let you do directly right now, but you can use core GIT commands\n\n\t$ git-checkout -b aspyk\n\nto create a new 'aspyk' head and switch to it, and\n\n\t$ git-checkout master\n\nto switch back to 'master' later, etc. Note that between the switching,\nCogito will work just fine even if your current head is not 'master'.\n\nYou can get the list of available heads by\n\n\t$ cg-status -g\n\nwhere the current head is marked by '>' and remote heads are marked by 'R'.\nYou can also get the list of source locations for remote heads by\n\n\t$ cg-branch-ls\n\n\n-- \n\t\t\t\tPetr \"Pasky\" Baudis\nStuff: http://pasky.or.cz/\nVI has two modes: the one in which it beeps and the one in which\nit doesn't.\n"},{"id":"9126","messageId":"Pine.LNX.4.58.0509220826460.2553@g5.osdl.org","threadId":"1913","inReplyTo":"E1EISTu-0000MI-Gz@jdl.com","subject":"Re: Please undo \"Use git-merge instead of git-resolve in","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-09-22T16:06:09Z","receivedAt":"2005-09-22T16:06:09Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Thu, 22 Sep 2005, Jon Loeliger wrote:\n> \n>     - Where some of the Git Frustration still lies\n\nBtw, I'd love to have more \"this frustrates me\" stories. I used to ask for \nthem from the (few) people that used git early on, just to see what the \nproblems were.\n\nI can't really help you with documentation, and would just hope that \npeople who figure out a problem they had would actually document it so \nthat others don't have to figure it out the hard way.\n\nBut if there is some usage pattern that doesn't make sense, post about it,\nand I can try to at least say why it happens that way (and then it's back\nto the \"please send a patch to the documentation\" case above ;). \n\nAlternatively, maybe it is something that doesn't need to happen at all, \nand it's just git being stupid, and we can just fix it.\n\nSo to look at your care.\n\n>     OK, so I have a git tree that looks like this:\n> \n>     241 % git show-branch --more=5\n>     * [jdl] Merge with rsync://www.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git\n>      ! [master] Merge branch 'master' of /home/src/linux-2.6/\n>       ! [origin] Merge branch 'master' of /home/src/linux-2.6/\n>        ! [paul] Merge with rsync://www.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git\n>     ----\n>     +  + [jdl] Merge with rsync://www.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git\n>     ++++ [master] Merge branch 'master' of /home/src/linux-2.6/\n>     ++++ [master~1] NTFS: Fix ntfs_{read,write}page() to cope with concurrent truncates better.\n>     ++++ [master~2] NTFS: Fix handling of compressed directories that I broke in earlier changeset.\n>     ++++ [master~3] NTFS: Fix various bugs in the runlist merging code.  (Based on libntfs\n>     ++++ [master~4] vc: Use correct size on buffer copy in vc_resize\n>     +  + [jdl~1] Merge rsync://rsync.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc-merge\n>     +  + [jdl^2] ppc32: Allow user to individual select CHRP/PMAC/PREP config\n>     +  + [jdl^2~1] powerpc: Merge simplified sections.h into asm-powerpc\n>     +  + [jdl^2~2] powerpc: Remove section free() and linker script bits\n>     +  + [jdl^2~3] powerpc: Remove sections use from ppc64 and drivers\n>     +  + [jdl^2~4] powerpc: Remove sections use from ppc\n>     +  + [jdl^2~5] ppc32: Removed non-inlined versions of local_irq* functions\n>     ++++ [jdl~2] Merge master.kernel.org:/home/rmk/linux-2.6-arm\n> \n>     I have current, modified, non-committed files in my working tree\n>     in the \"jdl\" branch.  I don't want to commit them now (yet).\n> \n>     I now know that Linus has updated his tree with new -rc2 parts.\n>     I want it.  In fact, I want it on the \"origin\" or \"master\" branch.\n>     (Or both.  And I don't know which.)\n> \n>     How do I get Linus' updates and merge them into the \"origin\" branch\n>     without changing to that branch first?\n> \n>     How do I get Paul's updates and merge them into the \"paul\" branch\n>     without changing to that branch first?\n> \n>     I think I can fetch the Linus updates by doing something like this:\n> \n> \tgit fetch origin\n\nYes, this works. This will fetch the new objects, and automatically update\nthe right branch (ie it will also update the \"origin\" branch).\n\n> \tgit fetch rsync://....path/to/linus-2.6-git\n\nThis will _not_ work. Or rather, it will \"work\" in the sense that it \nfetches the objects, but without a place to put them into, it won't update \nany of the branches, so it's kind of pointless.\n\n>     That will just grab the Objects and throw them into my .git/objects.\n> \n>     But how to do the merge?  I think that the merges all require\n>     the \"target branch\" to be the \"active\"/checkedout branch, right?\n>     I don't know how to now say \"Merge-up those new Objects on the\n>     origin branch\".\n\nThe first one should have done that already.\n\nYou can also specify _precisely_ what branches you want to use as a source \nand as a destination.\n\nIe\n\n\tgit fetch rsync:..../linus-2.6-git <src>:<dst>\n\nwill fetch the <src> branch (ie you'd usually use \"master\") from my tree \nand write it to the <dst> branch on your tree.\n\nAnd it's not a \"merge\" - it's just an update. A merge implies that you \ntake two trees that have had development on them and try to join them \ntogether. A \"git fetch\" does _not_ merge anything: it just _fetches_ the \nother side, and writes the objects (and top branch).\n\n>     I think what's confusing me still is that the previous\n>     World View According to CVS was essentially that you have\n>     this import branch into which you dragged all the external\n>     updates.  Then you merged that over to your working branch.\n>     And, you could easily have views of _both_ of those\n>     branches simultaneously.\n\nHmm.. I'm not sure exactly what you want, but\n\n\tgit fetch origin\n\nwill fetch my stuff without touching your changes AT ALL, and then you can \ndo things like\n\n\tgitk --all\n\nto see both your development series _and_ my stuff at the same time. And \nyes, it works fine even if you have \"dirty state\" in your tree.\n\n>     However, I _could_ just stick in my \"jdl\" working branch and\n>     directly pull-in and merge the linus changes.  I mean, my next\n>     step after pulling those changes into the so-called import\n>     branch was going to be to merge them to my branch anyway.\n\nAnd indeed, if you just did\n\n\tgit pull origin\n\nthen now you're doing a _pull_ instead of a fetch, which means that you do \nboth the fetch _and_ the merge.\n\nIn fact, if you use the shorthand with a named branch, the above really \n_will_ do a \"git fetch origin\" first, ie it will actually _update_ the \n\"origin\" branch before merging it into your current branch. So you'll have \n_both_.\n\nYou can see that (again) with\n\n\tgitk --all\n\nwhere you can actually see that \"origin\" got updated, and also merged into \nwhatever branch you were working on.\n\n>     OK, so let's say I did pull linus' update into the jdl branch.\n>     And they merge up nicely.  How do I now propogate _just_ the\n>     linus changes to the origin branch?  Again, I don't think I\n>     can without first checking out the \"origin\" branch.\n\nThe \"origin\" branch was already updated automatically if you used\n\n\tgit pull origin\n\nHowever, if you used\n\n\tgit pull rsync:..../linus-2.6.git\n\nthen git would only have fetched the objects, and _not_ updated the \n\"origin\" branch (because you didn't tell it about the \"origin\" branch). \n\nBut you can trivially fix that by doing\n\n\tgit fetch origin\n\nat this point, which will end up doing the equivalent of\n\n\tgit fetch rsync:..../linus-2.6.git master:origin\n\n(depending on what the contents of your .git/remotes/origin are, of \ncourse, the above is just an example).\n\n>     Am I missing something here?  Fighting against the tool?\n\nNo, you just didn't realize how \"git pull\" and \"git fetch\" worked. Git\nshould actually do what you want to do very naturally. Its' really how \nit's designed to work, you just didn't realize ;)\n\n>     So, you will all be pleased to know that I tried\n>     some stuff and was not successful.  In the \"jdl\"\n>     branch, I did a \"git pull linus\".  It happily went\n>     out and grabbed all the new objects from his tree.\n>     Spiffy.  It then announced that my branch of the\n>     working tree was \"dirty\" and quit.\n\nOk, it really depends on what your \".git/remotes/linus\" looks like.\n\nFor example, it _may_ just contain something like\n\n\tURL: rsync:..../linus2.6.git\n\nin which case there is no explicit heads specified. In that case, you \nreally should specify _which_ of the heads you want to pull, and what the \ntarget should be. For example, you can do that with\n\n\tgit fetch linus master:linus\n\nwhich says: \"fetch the branch 'master' from the repository described by \n'linus' (.git/remotes/linus) into _my_ branch 'linus'\".\n\nNOTE! This really is a _fetch_. It will fetch the objects, and _overwrite_ \nthe old value of the branch \"linus\".\n\nNow, you can specify that this is what you _always_ want to do, and \nactually set the branches in the \".git/remotes/linus\" file explicitly. You \ncan make your .git/remotes/linus file look like this instead:\n\n\tURL: rsync:..../linus2.6.git\n\tPull: master:linus\n\nand now you've told it that whenever you fetch (or pull) from \"linus\", you\nwant to fetch the \"master\" branch from the remote end, and you always want\nto store it in the \"linus\" branch in the local repository.\n\nNOTE NOTE NOTE! Your branch-name does _not_ have to match the shorthand \nname. So you can make the \"Pull:\" line say \"master:linus-branch\", and that \nwill mean that when you do \"git fetch linus\", it will update the \n\"linus-branch\" instead.\n\nStill with me?\n\nFinally (or _instead_ of the \"fetch\"), we can do\n\n\tgit pull linus\n\nnow. It will do the fetch, and since you now specify a destination in your \n\"remotes/linus\" file, it will always update the \"linus\" part (it a \"git \npull\" is a _superset_ of what \"git fetch\" does). But in _addition_ to \nfetching the \"linus\" branch, it will then try to merge it.\n\nNow, this is where \"dirty\" comes in. The merge will fail if you have \nchanged any files that the merge wants to modify. So do a\n\n\tgit diff --name-only HEAD\n\nto see if there are any changes, and commit them - or undo them - if so.  \nThen try to pull again.\n\t\n\t\tLinus\n"}]}