{"thread":{"id":"22807","subject":"confusion over git-cherry-pick, git-merge and git-cherry","startedAt":"2010-02-24T21:39:23Z","lastAt":"2010-02-24T23:07:01Z","messageCount":2,"participants":["Kevin Green","Thomas Rast"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"135617","messageId":"20100224213923.GV14244@morganstanley.com","threadId":"22807","inReplyTo":null,"subject":"confusion over git-cherry-pick, git-merge and git-cherry","fromName":"Kevin Green","fromEmail":"kevin.t.green@morganstanley.com","sentAt":"2010-02-24T21:39:23Z","receivedAt":"2010-02-24T21:39:23Z","isPatch":false,"sender":{"key":"kevin.t.green@morganstanley.com","avatar":null},"body":"\nHi,\n\n\nGiven this scenario:\n\n  Work is done over a series of commits on branch 'alpha'.  A commit is\n  cherry-pick'd from 'alpha' onto branch 'beta'.  Later, branch 'alpha'\n  is merged into branch 'beta', I'm seeing unexpected output from\n  git-cherry.\n\n  Here's what the history currently looks like:\n\n\n                      B'-----M beta\n                    /       /\n               o---A---B---C alpha\n\n\nI would expect git-cherry to recognize that B' has the same content as\nB and thus show me a '-' sign in front.  Instead, I get the following\noutput from 'git-cherry alpha beta'\n\n  $ git cherry alpha beta\n  + B'\n\nThe output of git-log looks like this (which is also unfortunate):\n\n  $ git log --pretty=oneline\n  M  Merge branch 'alpha' into beta\n  B' change 2\n  C  change 3\n  B  change 2\n  A  change 1\n  o  initial commit\n\n\nThe output of git-patch-id for B and B' is identical.  \n\nCan someone please explain to me why git-cherry doesn't notice that the\nduplicate commit has the same content?  Shouldn't it?   Shouldn't I get\nthe following output:\n\n  $ git cherry alpha beta\n  - B'\n\nthat is, there exists a commit on beta that doesn't exist in alpha, but\nthe content there is the same?\n\n\nHow do others deal with cherry-pick and merge combined together?\n\n\nTo give some further background on what I'm trying to do, I would like\nto prevent changes getting made in the beta branch that don't already\nexist in alpha.  I'm enforcing this with a server side hook that does a\ngit-cherry and checks if any of the lines start with a '+'.  This works\ngreat until I allow changes to be cherry-picked from alpha.  The first\ncherry-pick works, but then when the whole of alpha is later merged in,\nthe hook fails to allow any subsequent push to 'beta'.\n\n\nThanks\n\n--Kevin\n"},{"id":"135626","messageId":"201002250007.01934.trast@student.ethz.ch","threadId":"22807","inReplyTo":"20100224213923.GV14244@morganstanley.com","subject":"Re: confusion over git-cherry-pick, git-merge and git-cherry","fromName":"Thomas Rast","fromEmail":"trast@student.ethz.ch","sentAt":"2010-02-24T23:07:01Z","receivedAt":"2010-02-24T23:07:01Z","isPatch":false,"sender":{"key":"tr@thomasrast.ch","avatar":"https://avatars.githubusercontent.com/u/153510?v=4"},"body":"On Wednesday 24 February 2010 22:39:23 Kevin Green wrote:\n>   Here's what the history currently looks like:\n>\n>\n>                       B'-----M beta\n>                     /       /\n>                o---A---B---C alpha\n>\n>\n> I would expect git-cherry to recognize that B' has the same content as\n> B and thus show me a '-' sign in front.  Instead, I get the following\n> output from 'git-cherry alpha beta'\n>\n>   $ git cherry alpha beta\n>   + B'\n[...]\n> Can someone please explain to me why git-cherry doesn't notice that the\n> duplicate commit has the same content?  Shouldn't it?   Shouldn't I get\n> the following output:\n>\n>   $ git cherry alpha beta\n>   - B'\n\nThe problem here is that when looking at the range alpha..beta as\nabove, git-cherry only filters out commits in beta..alpha.  I suspect\nthis is an optimization decision, to avoid having to scan more\nhistory.  It's sort-of implied in the manpage when talking about the\nfork-point [which is an extremely old term for the merge-base from the\nvery first docs back in 52a22d1 ([PATCH] Subject: [PATCH] Add some\ndocumentation., 2005-08-26)!].\n\nNow of course your merge means beta..alpha is empty.\n\nBy the way, git log --left-right --cherry-pick alpha...beta does the\nsame.\n\n> To give some further background on what I'm trying to do, I would like\n> to prevent changes getting made in the beta branch that don't already\n> exist in alpha.  I'm enforcing this with a server side hook that does a\n> git-cherry and checks if any of the lines start with a '+'.  This works\n> great until I allow changes to be cherry-picked from alpha.  The first\n> cherry-pick works, but then when the whole of alpha is later merged in,\n> the hook fails to allow any subsequent push to 'beta'.\n\nI tried to come up with a neat solution, possibly using boundary\ncommits, but unfortunately there seems to be another problem.  Suppose\nyour history is this:\n\n  *   79a8170 (HEAD, beta) Merge branch 'alpha' into beta\n  |\\\n  | * 5c8e233 (alpha) Revert \"B\"\n  * | 26f9c5f B\n  | * 1d5e497 B\n  | * a1eaae7 bar\n  |/\n  * 8c675da foo\n\nI.e., after B was cherry-picked over to beta, it was reverted on\nalpha.  In the presumed \"unstable\" and \"more stable\" branch I'm\nreading into your model, this probably indicates that B was bad and\nneeds to be thrown out.\n\nThe merge, however, appears to \"resurrect\" the change because it only\nlooks at the differences between the merge-base (foo) and alpha/beta,\nrespectively.  This is the right behaviour for a merge: one side did a\nchange B where the other did nothing.\n\nSo no matter how well you filter your beta branch, this model doesn't\ngive the right results anyway.\n\nThat being said, you can obviously brute force your idea by checking\nwhether all patch ids in 'git log -p old-beta..beta | git patch-id'\nalso appear in 'git log -p alpha | git patch-id', where 'old-beta' is\nwhat the hook got as the old value of 'beta'.  It will just get\nunbearably slow really quick because the latter is an unrestricted\n'log' and runs all the way back to your history *while generating\ndiffs*, so you'll want to cache that list and only add the new ones as\nthey arrive.\n\n> The output of git-log looks like this (which is also unfortunate):\n>\n>   $ git log --pretty=oneline\n>   M  Merge branch 'alpha' into beta\n>   B' change 2\n>   C  change 3\n>   B  change 2\n>   A  change 1\n>   o  initial commit\n\nWhy is that unfortunate?\n\nIf you mean the ordering, look into --topo-order or --date-order.\n\n--\nThomas Rast\ntrast@{inf,student}.ethz.ch\n"}]}