Yann Dirson <dirson@xxxxxxxxx> writes: > On Mon, 17 Dec 2012 13:14:56 -0800 > Junio C Hamano <gitster@xxxxxxxxx> wrote: > >> Andreas Schwab <schwab@xxxxxxxxxxxxxx> writes: >> >> > Christian Couder <christian.couder@xxxxxxxxx> writes: >> > >> >> Yeah, at one point I wanted to have a command that created to craft a >> >> new commit based on an existing one. >> > >> > This isn't hard to do, you only have to resort to plumbing: >> > >> > $ git cat-file commit fef11965da875c105c40f1a9550af1f5e34a6e62 | sed s/bfae342c973b0be3c9e99d3d86ed2e6b152b4a6b/790c83cda92f95f1b4b91e2ddc056a52a99a055d/ | git hash-object -t commit --stdin -w >> > bb45cc6356eac6c7fa432965090045306dab7026 >> >> Good. I do not think an extra special-purpose command is welcome >> here. > > Well, I'm not sure this is intuitive enough to be useful to the average user :) I do not understand why you even want to go in the harder route in the first place, only to complicate things? All you want to do is to craft a commit object that records a specific tree shape, has a set of parents you want, and has the log information you want. Once you have the commit, you can replace an unwanted commit with it. ----A----B----o---- .... X----Y----Z---- .... Suppose you want to pretend that X is a child of A, even though it is not in the real life. So you want to create a commit that - has the same tree as X; - has A as its parent; and - records log and authorship of X. and then use "git replace" to replace X, right? How about doing it this way? $ git checkout X^0 ;# detach $ git reset --soft A $ git commit -C X The first gives you the index and the working tree that is the same as X, the second moves HEAD while keeping the index and the working tree so that the commit you create will be a child of A, and the last makes that commit with the metainformation from X [*1*]. If you want, you can even tweak the contents of the tree before making the commit in the final step, or tweak the log message during the final step. Then you can take the resulting commit and replace X with it, no? Alternatively, you can do: $ git checkout X^0 ;# detach $ git reset --soft B $ git commit --amend -C X that is, find an existing commit B that has the desired set of parents, and amend it with the same tree and the metainformation as X. This would even work when you want to come up with a commit that replaces a merge. For example, if you want to pretend that B were a merge between A and X in the above topology, you could $ git checkout -b temp A $ git merge -s ours X ;# the recorded tree does not matter $ git checkout B^0 ;# detach $ git reset --soft temp $ git commit --amend -c B which would create one merge that has the desired set of parents (i.e. A and X) in the first two steps on temp branch, prepares the index and the working tree to match the tree of B, and with that tree and the metainformation from B, amends that merge. The resulting commit will be a merge between A and X that has the tree of B and metainformation of B (with a chance to edit it further, as I used -c there). Is this not intuitive enough? [Footnote] *1* If you are not tweaking the tree contents, you can do this all in the index without affecting the working tree, e.g. $ git checkout HEAD^0 ;# totally random state unrelated to X nor A $ git read-tree X ;# just update the index to match tree of X $ git reset --soft A ;# next commit will be child of A $ git commit -C X ;# and with metainformation from X After you are done, you can "read-tree $branch" followed by "checkout $branch" to come back to where you were. -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html