Re: [SCRIPT/RFC 0/3] git-commit --onto-parent (three-way merge, no working tree file changes)

2017-12-08 Thread Igor Djordjevic
Hi Alexei,

On 09/12/2017 03:18, Alexei Lozovsky wrote:
> 
> > Chris reported in this very topic[1] that sometimes, due to
> > conflicts with later commits, "checkout > commit > [checkout >]
> > rebase --onto" is "much easier to do", where "commit --fixup >
> > rebase -i" "breaks" (does not apply cleanly).
> 
> It was more of a rant about conflict resolution by rebase rather than
> a concern about modification time of files. While I'd prefer git to
> not touch the source tree unnecessarily, it's not really a big deal
> for me if it does and some parts of the project need to be rebuilt.

Nevertheless, I found it valuable in supporting the case where 
"commit --fixup > rebase -i" seems to require even more work than 
otherwise necessary :)

But thanks for clarifying, anyway, it does feel like `git rebase -i 
--autosquash` could be smarter in this regards, if `git rebase 
--onto` does it better...?

Even though your explanation seems clear, having a real, easily 
reproducible case would help as well, I guess.

> I kinda hoped that you may know this magic and incorporate it into 
> "commit --onto" which will allow to immediately get to the result of 
> the rebase:
> 
>   ---A---f!A---B'
> 
> without spelling it all manually.

If you mind enough to be bothered testing it out, might be even 
existing/initial state of originally proposed `git commit 
--onto-parent` script would work for you, as it does incorporate some 
trivial three-way merge resolution.

In your starting situation:

---A---B

... you would just do something like:

git commit --onto-parent A

... hopefully ending up in the desired state (hopefully = conflicts 
automatically resolved):

---A---C---B'

You could even do this instead:

git commit --onto-parent A --amend

... ending up with:

---A'---B'

... as that is basically what you wanted in the first place ;)

> (And yeah, I'm actually Alexei, not Chris. That was my MUA being
> dumb and using an old pseudonym than Google insists I'm called by.)

Ah, sorry for the confusion :)

Regards, Buga


Re: [SCRIPT/RFC 0/3] git-commit --onto-parent (three-way merge, no working tree file changes)

2017-12-08 Thread Alexei Lozovsky
On Dec 9, 2017, at 01:54, Igor Djordjevic wrote:
> On 08/12/2017 17:24, Junio C Hamano wrote:
>> I'd rather do a quick fix-up on top (which ensures that at least the
>> fix-up works in the context of the tip), and then "rebase -i" to
>> move it a more appropriate place in the history (during which I have
>> a chance to ensure that the fix-up works in the context it is
>> intended to apply to).
> 
> Chris reported in this very topic[1] that sometimes, due to conflicts 
> with later commits, "checkout > commit > [checkout >] rebase --onto" 
> is "much easier to do", where "commit --fixup > rebase -i" "breaks" 
> (does not apply cleanly).

It was more of a rant about conflict resolution by rebase rather than
a concern about modification time of files. While I'd prefer git to
not touch the source tree unnecessarily, it's not really a big deal
for me if it does and some parts of the project need to be rebuilt.

The situations which tend to cause conflicts for me usually look
like this.

  ---A---B

Say, a file has this line added somewhere in commit A:

  +int some_function(); 

Then commit B adds another line:

   int some_function(); 
  +int another_function();

Then I realize that I would like to have commit A to introduce some
other_function() as well, so I add a fixup:

  ---A---B---f!A

with the following diff:

   int some_function(); 
  +int other_function();
   int another_function();

And then I often find that "rebase -i --autosquash" fails to apply
the commit B because it expects slightly different context around
the changed lines.

However, sometimes I see that if I do this:

  ---A---B
  \
   f!A

then "rebase --onto f!A A B" succeeds, nicely resolving the conflict
without bothering me. No idea why. I kinda hoped that you may know
this magic and incorporate it into "commit --onto" which will allow
to immediately get to the result of the rebase:

  ---A---f!A---B'

without spelling it all manually.

(And yeah, I'm actually Alexei, not Chris. That was my MUA being dumb
and using an old pseudonym than Google insists I'm called by.)


Re: [SCRIPT/RFC 0/3] git-commit --onto-parent (three-way merge, no working tree file changes)

2017-12-08 Thread Igor Djordjevic
On 08/12/2017 17:24, Junio C Hamano wrote:
> 
> > To get back on track, and regarding what`s already been said,
> > would having something like this(1) feel useful?
> >
> > (1) git commit --onto 
> 
> Are you asking me if _I_ find it useful?  It is not a very useful
> question to ask, as I've taken things that I do not find useful
> myself.

It was also (kind of shy and subtle) "would you take it?", indeed, 
but I do value your personal opinion here, too, being a recognized 
developer, and one really knowing the Git (mailing list) community on 
top of it, so I appreciate you addressed both sides of the question.

And it was partly addressed to Hannes, but more for a confirmation, I 
guess, him being the one to favor such a flow in the first place, 
over what I initially suggested.

> Having said that, I do not see me personally using it. You keep
> claiming that committing without ever materializing the exact state
> that is committed in the working tree is a good thing.
> 
> I do not subscribe to that view.  

No - and I find it an important difference to note - just that it 
might be acceptable / more preferable _in certain situations_, where 
the only alternative seems to be wasting (significant) amount of time 
on needless rebuilds of many files (just because of branch switching, 
otherwise untouched by the changes we`re interested in).

If this is perceived a too uncommon/exotic case to worth addressing 
is a different matter, though.

> I'd rather do a quick fix-up on top (which ensures that at least the
> fix-up works in the context of the tip), and then "rebase -i" to
> move it a more appropriate place in the history (during which I have
> a chance to ensure that the fix-up works in the context it is
> intended to apply to).

Chris reported in this very topic[1] that sometimes, due to conflicts 
with later commits, "checkout > commit > [checkout >] rebase --onto" 
is "much easier to do", where "commit --fixup > rebase -i" "breaks" 
(does not apply cleanly).

> I know that every time I say this, people who prefer to commit
> things that never existed in the working tree will say "but we'll
> test it later after we make these commit without having their state
> in the working tree".  But I also know better that "later" often do
> not come, ever, at least for people like me ;-).

No comment here ;)

> The amount of work _required_ to record the fix-up at its final
> resting place deeper in the history would be larger with "rebase -i"
> approach, simply because approaches like "commit --onto" and "git
> post" that throw a new commit deep in the history would not require
> ever materializing it in the working tree.  But because I care about
> what I am actually committing, and because I am just lazy as any
> other human (if not more), I'd prefer an apporach that _forces_ me
> to have a checkout of the exact state that I'd be committing.  That
> would prod me to actually looking at and testing the state after the
> change in the context it is meant to go.

All that I agree with, too.

But that said, I do find `git add --patch` invaluable (for example), 
where one can still opt to commit right away (and test later ;)), or 
do a proper `git stash push --keep-index` first in order to actually 
check/test the exact state/context before committing.

One of the biggest advantages I see in using Git is that it provides 
so many possibilities, where there is not necessarily a single 
"correct" way to do something - depending on the (sub)context, the 
decision on "_the_ correct" way can be deferred to the user himself.

Git (usually) does not judge, except in cases where something is 
considered "plain wrong" - still different than "might not be the 
best approach", but not necessarily a wrong one, either.

But I do realize it also means more chances for beginner users to 
shoot themselves in the foot, blaming it on Git, so even if just a 
matter of personal taste, a more restrictive preference from the Git 
maintainer is understandable :)

Regards, Buga

[1] 
https://public-inbox.org/git/CAPc5daWupO6DMOMFGn=xjucg-jmyc4eyo8+tmasdwcaohxz...@mail.gmail.com/T/#m989306ab9327e15f14027cfd74ae8c5bf487affb


Re: [SCRIPT/RFC 0/3] git-commit --onto-parent (three-way merge, no working tree file changes)

2017-12-08 Thread Junio C Hamano
Igor Djordjevic  writes:

> To get back on track, and regarding what`s already been said, would 
> having something like this(1) feel useful?
>
> (1) git commit --onto 

Are you asking me if _I_ find it useful?  It is not a very useful
question to ask, as I've taken things that I do not find useful
myself.

Having said that, I do not see me personally using it.  You keep
claiming that committing without ever materializing the exact state
that is committed in the working tree is a good thing.

I do not subscribe to that view.  

I'd rather do a quick fix-up on top (which ensures that at least the
fix-up works in the context of the tip), and then "rebase -i" to
move it a more appropriate place in the history (during which I have
a chance to ensure that the fix-up works in the context it is
intended to apply to).

I know that every time I say this, people who prefer to commit
things that never existed in the working tree will say "but we'll
test it later after we make these commit without having their state
in the working tree".  But I also know better that "later" often do
not come, ever, at least for people like me ;-).

The amount of work _required_ to record the fix-up at its final
resting place deeper in the history would be larger with "rebase -i"
approach, simply because approaches like "commit --onto" and "git
post" that throw a new commit deep in the history would not require
ever materializing it in the working tree.  But because I care about
what I am actually committing, and because I am just lazy as any
other human (if not more), I'd prefer an apporach that _forces_ me
to have a checkout of the exact state that I'd be committing.  That
would prod me to actually looking at and testing the state after the
change in the context it is meant to go.


Re: [SCRIPT/RFC 0/3] git-commit --onto-parent (three-way merge, no working tree file changes)

2017-12-07 Thread Igor Djordjevic
On 06/12/2017 19:34, Johannes Sixt wrote:
> 
> I am sorry for not responding in detail. I think we've reached a 
> mutual understanding of our workflows.

No problem, thanks for your time so far.

There might be one more thing I should address, possibly left unclear 
from my previous message, but I`ll leave that for a follow-up e-mail, 
not being that important at the moment for the topic itself.

On 06/12/2017 19:40, Junio C Hamano wrote:
> 
> > Though, from the ideas you tossed around most recently, you seem to
> > want to make git-commit into a kitchen-sink for everything. I have
> > my doubts that this will be a welcome change. Just because new
> > commits are created does not mean that the feature must live in
> > git-commit.
> 
> Nicely put.

Yeah, I understand that might have felt cluttering, besides also 
being out of scope of the original topic idea. Thanks for the reality 
check (to both).

To get back on track, and regarding what`s already been said, would 
having something like this(1) feel useful?

(1) git commit --onto 

So in previously mentioned situation:

(2) ...A...C<- topics A, C
\   \
  ---o---o---o---o I<- integration <- HEAD
/   /
...B...D<- topics B, D

... it would allow committing changes F inside HEAD on top of B 
directly, no checkout / branch switching needed, getting to:

(3) ...A...C<- topics A, C
\   \
  ---o---o---o---o I<- integration <- HEAD
/   /
...B...D<- topic D
\
 F  <- topic B

So the most conservative approach, where changes F are removed from 
HEAD index and working tree, leaving it up to the user to decide if 
he will then merge them back in (or do something else).

I stress the major selling point here still being avoiding branch 
switching back and forth in order to commit a fixup on a different 
branch, which could otherwise trigger needless rebuilds, being 
significant in large projects.

And thanks to that `git-merge-one-file--cached`[1] script, we are 
also able to resolve some more of trivial conflicts when applying F 
onto B, using three-way file merge when needed, but still not 
touching working tree (contrary to original `git-merge-one-file`).

Regards, Buga

[1] 
https://public-inbox.org/git/CAPc5daWupO6DMOMFGn=xjucg-jmyc4eyo8+tmasdwcaohxz...@mail.gmail.com/T/#mcb3953542dc265516e3ab1bff006ff1b5b85126a


Re: [SCRIPT/RFC 0/3] git-commit --onto-parent (three-way merge, no working tree file changes)

2017-12-06 Thread Junio C Hamano
On Wed, Dec 6, 2017 at 10:34 AM, Johannes Sixt  wrote:
> I am sorry for not responding in detail. I think we've reached a mutual
> understanding of our workflows.
>
> Though, from the ideas you tossed around most recently, you seem to want to
> make git-commit into a kitchen-sink for everything. I have my doubts that
> this will be a welcome change. Just because new commits are created does not
> mean that the feature must live in git-commit.

Nicely put.


Re: [SCRIPT/RFC 0/3] git-commit --onto-parent (three-way merge, no working tree file changes)

2017-12-06 Thread Johannes Sixt
I am sorry for not responding in detail. I think we've reached a mutual 
understanding of our workflows.


Though, from the ideas you tossed around most recently, you seem to want 
to make git-commit into a kitchen-sink for everything. I have my doubts 
that this will be a welcome change. Just because new commits are created 
does not mean that the feature must live in git-commit.


-- Hannes



Re: [SCRIPT/RFC 0/3] git-commit --onto-parent (three-way merge, no working tree file changes)

2017-12-03 Thread Igor Djordjevic
Hi Hannes,

On 01/12/2017 18:23, Johannes Sixt wrote:
> 
> > To work with `--onto-parent` and be able to commit on top of any of
> > the topic branches, you would need a situation like this instead:
> >
> >   (1)  ...C  <- topic C
> >   |
> >  ...A |  <- topic A
> >  \|
> >...o I<- integration
> >  /|
> >  ...B |  <- topic B
> >   |
> >...D  <- topic D
> 
> This is a very, VERY exotic workflow, I would say. How would you
> construct commit I when three or more topics have conflicts?
> merge-octopus does not support this use-case.

But I`m not interested in constructing commit I in the first place, 
only help working with it once it`s already there (which shouldn`t be 
too uncommon in case of unrelated, non-conflicting topics) - but I 
already agreed my example could have been a bit too esoteric, 
distracting attention from the important part :)

I`ll continue on this further below, where you commented on those 
more common scenarios.

Here, let`s try to look at the whole situation from a "patch queue" 
perspective instead, starting from something like this:

(5) ---O---I  <- integration <- HEAD

... and then making progress like this - first, commit A1 onto O, 
starting "topicA" branch at the same time, even, maybe using syntax 
like `git commit --onto-parent O -b topicA`:

(6) ---O---J  <- integration <- HEAD   [ J = I + A1 ]
\ /
 A1   <- topicA

..., then commit B1 onto O to start "topicB" branch:

(7)  B1   <- topicB
/ \
---O---K  <- integration <- HEAD   [ K = J + B1 ]
\ /
 A1   <- topicA

..., then add one more commit (patch) onto B1:

(8)  B1---B2   <- topicB
/  \
---OL  <- integration <- HEAD  [ L = K + B2 ]
\  /
 A1---/<- topicA

..., and one more, B3:

(9)  B1---B2---B3   <- topicB
/   \
---O-M  <- integration <- HEAD [ M = L + B3 ]
\   /
 A1/<- topicA

We can also start a new topic branch (queue), commit C1:

(10) B1---B2---B3   <- topicB
/   \
---O-N  <- integration <- HEAD [ N = M + C1 ]
   |\   /|
   | A1/ /  <- topicA
   \/
C1-/<- topicC

And lets make one more "topicA" related commit A2:

(11) B1---B2---B3   <- topicB
/   \
---O-P  <- integration <- HEAD [ P = N + A2 ]
   |\   /|
   | A1---A2---/ /  <- topicA
   \/
C1-/<- topicC


Notice how HEAD never leaves "integration" branch, and underlying 
commit is recreated each time? It`s like a live branch we`re working 
on, but we`re not actually committing to.

No branch switching (and no working tree file changes caused by it), 
and we`re working on multiple topics/branches simultaneously, being 
able to instantly test their mutual interaction as we go, but also 
creating their separate (and "clean") histories at the same time.

I guess this would make most sense with simple topics we _could_ 
practically work on at the same time without making our life too 
complicated - what stands for "git add --patch", too, when working on 
multiple commits at the same time.

Once satisfied, of course each topic branch would need to be tested 
separately, and each commit, even - all the same as with "git add 
--patch" commits.

And "git add --patch" can still be used here, too, to distribute 
partial changes, currently existing together inside the working tree, 
to different topic branches, at the time of making the commit itself.

Does this approach make more sense in regards to "git commit 
--onto-parent" functionality I`m having in mind? Or I`m dreaming too 
much here...? :)

> > Once there, starting from your initial position:
> >
> > > ...A...C<- topics A, C
> > > \   \ E
> > >   ---o---o---o---o I<- integration <- HEAD
> > > /   /
> > > ...B...D<- topics B, D
> >
> > ... and doing something like `git commit --onto B --merge` would
> > yield:
> > 
> > (3) ...A...C<- topics A, C
> >   \   \ E
> > ---o---o---o---o I'   <- integration
> >   /   /|
> >   ...B...D |  <- topic D
> >   \|
> >f---'  <- topic B
> >
> > ... where (I' = I + f) is still true.
> 
> I am not used to this picture. I would not think that it is totally
> unacceptable, but it still has a hmm-factor.

Main idea is not to pile up uninteresting merge commits inside 
(throwaway) integration branch, needlessly complicating history, but 
pretend as we just made the integration merge, where fixup commit f 
was already existing in its topic branch prior the merge.

> > If that`s preferred in some
> > cases, it could even look like this 

Re: [SCRIPT/RFC 0/3] git-commit --onto-parent (three-way merge, no working tree file changes)

2017-12-03 Thread Igor Djordjevic
Hi Chris,

On 30/11/2017 23:40, Chris Nerwert wrote:
> 
> I'm actually doing the described workflow quite often with git rebase
> when working on a topic. Given the following structure:
> 
>   ---o   (master)
>   \
>o---A---B---C (topic)
> 
> When I want to make changes to commit A one option is to make them
> directly on topic, then do "git commit --fixup A", and then eventual
> interactive rebase onto master will clean them up:
> 
>   ---o (master)
>   \
>o---A---B---C---f!A (topic)
> 
> However, sometimes this breaks when changes in B or C conflict
> somehow with A (which may happen quite a lot during development of a
> topic), so the rebase will not apply cleanly. So sometimes I make a
> temporary branch from A, commit the fixup there:
> 
>   ---o   (master)
>   \
>o---A---B---C (topic)
> \
>  f!A (temp)
> 
> and then use "git rebase --onto temp A topic" to move the topic back
> on track:
> 
>   ---o (master)
>   \
>o---A---f!A (temp)
>   \
>B'---C' (topic)
> 
> after which the final cleanup rebase is much easier to do.
> 
> Obviously, all the branch switching and rebasing does take its tall
> on file modifications.

>From use case you described (and which I often experience myself), it 
seems plain "git commit --onto A" would be of help here, committing 
fixup onto A directly, without a need to switch to it (branch or 
not), a case I`m discussing with Hannes in that other sub-thread[1] of 
this e-mail, too.

But from there, your flow takes a different direction, using rebase, 
while this whole thread started around some merge-like functionality.

I can imagine a user interface doing what you (and I) would like, 
something like:

(1) git commit --onto A --rebase

..., where your changes would first be committed onto commit A, and 
then commits from A (excluded) to HEAD (included) rebased onto this 
new commit.

BUT, as far as it seems to me, rebase currently touches working tree 
for each operation (am I wrong here?), so once the rebase sequence is 
initiated, it would internally still need to checkout to your new 
fixup commit (on top of A), and then proceed applying changes and 
changing working tree with each commit being rebased, overall failing 
to address your main concern - needless (untouched) file 
modifications, even in case of no conflicts.

I find this scenario quite interesting as well, but I`m afraid it may 
currently be out of scope of what I`m trying to accomplish with "git 
commit --onto[-parent]", for the most part because it looks like it 
would need "index only rebase" first (not touching working tree, that 
is)...?

If we had that, it would/should be pretty easy to add it into the mix 
with "git commit --onto" here, ending up with something as imagined 
in command line (1) above :) I`ll make a note of it, thanks.

Any further help appreciated, of course :)

Regards, Buga

[1] 
https://public-inbox.org/git/0f30bef8-a9f7-43b9-bc89-4b9cd7af3...@gmail.com/T/#me830a80d745df60ae8bd6a2e67eee4bd4dabf56c


Re: [SCRIPT/RFC 0/3] git-commit --onto-parent (three-way merge, no working tree file changes)

2017-12-01 Thread Johannes Sixt

Am 30.11.2017 um 00:10 schrieb Igor Djordjevic:

On 29/11/2017 20:11, Johannes Sixt wrote:

With git-post, I make a fixup commit commit on the integration
branch, then `git post B && git merge B`:

  ...A...C  <- topics A, C
  \   \
---o---o---o---o---f---F<- integration
  /   /   /
  ...B...D   /  <- topic D
  \ /
   f'--'<- topic B

The merge F does not introduce any changes on the integration branch,
so I do not need it, but it helps keep topic B off radar when I ask
`git branch --no-merged` later.


But you`re not committing (posting) on your HEAD`s (direct) parent in
the first place (topic B), so `commit --onto-parent` isn`t right tool
for the job... yet :)


Ohh..kay.


To work with `--onto-parent` and be able to commit on top of any of
the topic branches, you would need a situation like this instead:

  (1)  ...C  <- topic C
  |
 ...A |  <- topic A
 \|
   ...o I<- integration
 /|
 ...B |  <- topic B
  |
   ...D  <- topic D


This is a very, VERY exotic workflow, I would say. How would you 
construct commit I when three or more topics have conflicts? 
merge-octopus does not support this use-case.



With `commit --onto-parent` you would skip `git post B && git merge
B` steps, where "fixup commit" would be done with `--onto-parent B`,
So you end up in situation like this:

  (2)  ...C  <- topic C
  |
 ...A |  <- topic A
 \|
   ...o I'   <- integration
 /|
 ...B---f |  <- topic B
  |
   ...D  <- topic D

State of index and working tree files in your F and my I' commit is
exactly the same (I' = I + f), where in my case (2) history looks
like "f" was part of topic B from the start, before integration
merge happened.

BUT, all this said, I understand that your starting position, where
not all topic branches are merged at the same time (possibly to keep
conflict resolution sane), is probably more often to be encountered
in real-life work... and as existing `--onto-parent` machinery should
be able to support it already, I`m looking forward to make it happen :)

Once there, starting from your initial position:


...A...C<- topics A, C
\   \ E
  ---o---o---o---o I<- integration <- HEAD
/   /
...B...D<- topics B, D


... and doing something like `git commit --onto B --merge` would yield:
  
  (3) ...A...C<- topics A, C

  \   \ E
---o---o---o---o I'   <- integration
  /   /|
  ...B...D |  <- topic D
  \|
   f---'  <- topic B

... where (I' = I + f) is still true.


I am not used to this picture. I would not think that it is totally 
unacceptable, but it still has a hmm-factor.



If that`s preferred in some
cases, it could even look like this instead:

  (4) ...A...C <- topics A, C
  \   \ E  I
---o---o---o---o---F   <- integration
  /   /   /
  ...B...D   / <- topic D
  \ /
   f---'   <- topic B

... where F(4) = I'(3), so similar situation, just that we don`t
discard I but post F on top of it.


This is very acceptable.

Nevertheless, IMO, it is not the task of git-commit to re-compute a 
merge commit. It would be OK that it commits changes on top of a branch 
that is not checked out. Perhaps it would even be OK to remove the 
change from the current workspace (index and worktree), because it will 
return in the form of a merge later, but producing that merge is 
certainly not the task of git-commit.


-- Hannes


Re: [SCRIPT/RFC 0/3] git-commit --onto-parent (three-way merge, no working tree file changes)

2017-11-30 Thread Chris Nerwert
On Nov 27, 2017, at 00:35, Igor Djordjevic  wrote:
> Approach discussed here could have a few more useful applications, 
> but one seems to be standing out the most - in case where multiple 
> topic branches are temporarily merged for integration testing, it 
> could be very useful to be able to post "hotfix" commits to merged 
> branches directly, _without actually switching to them_ (and thus 
> without touching working tree files), and still keeping everything 
> merged, in one go.
I'm actually doing the described workflow quite often with git rebase when 
working on a topic. Given the following structure:

  ---o   (master)
  \
   o---A---B---C (topic)

When I want to make changes to commit A one option is to make them directly on 
topic, then do "git commit --fixup A", and then eventual interactive rebase 
onto master will clean them up:

  ---o (master)
  \
   o---A---B---C---f!A (topic)

However, sometimes this breaks when changes in B or C conflict somehow with A 
(which may happen quite a lot during development of a topic), so the rebase 
will not apply cleanly. So sometimes I make a temporary branch from A, commit 
the fixup there:

  ---o   (master)
  \
   o---A---B---C (topic)
\
 f!A (temp)

and then use "git rebase --onto temp A topic" to move the topic back on track:

  ---o (master)
  \
   o---A---f!A (temp)
  \
   B'---C' (topic)

after which the final cleanup rebase is much easier to do.

Obviously, all the branch switching and rebasing does take its tall on file 
modifications.

Re: [SCRIPT/RFC 0/3] git-commit --onto-parent (three-way merge, no working tree file changes)

2017-11-29 Thread Igor Djordjevic
Hi Hannes,

On 29/11/2017 20:11, Johannes Sixt wrote:
> 
> Ok, then please explain, how this process should work in my workflow
> and with the `commit --onto-parent` feature that you have in mind. I
> have an integration branch (which is a throw-away type, so you can
> mangle it in any way you want); it is a series of merges:
> 
>  ...A...C<- topics A, C
>  \   \ E
>---o---o---o---o I<- integration
>  /   /
>  ...B...D<- topics B, D
> 
> Now I find a bug in topic B. Assume that the merges of C and D have
> textual conflicts with the integration branch (but not with B) and/or
> may be evil. What should I do?
> 
> With git-post, I make a fixup commit commit on the integration
> branch, then `git post B && git merge B`:
> 
>  ...A...C  <- topics A, C
>  \   \
>---o---o---o---o---f---F<- integration
>  /   /   /
>  ...B...D   /  <- topic D
>  \ /
>   f'--'<- topic B
> 
> The merge F does not introduce any changes on the integration branch,
> so I do not need it, but it helps keep topic B off radar when I ask
> `git branch --no-merged` later.

But you`re not committing (posting) on your HEAD`s (direct) parent in 
the first place (topic B), so `commit --onto-parent` isn`t right tool 
for the job... yet :)

To make it easier to explain, I marked your integration branch 
initial head with "I" in the quote above (commit merging-in branch 
D), and marked commit merging-in branch C with "E".

HEAD being currently on commit "I", you can only use `--onto-parent` 
option to commit onto "E" or "D", being parents of "I".

To work with `--onto-parent` and be able to commit on top of any of 
the topic branches, you would need a situation like this instead:

 (1)  ...C  <- topic C
 |
...A |  <- topic A
\|
  ...o I<- integration
/|
...B |  <- topic B
 |
  ...D  <- topic D

With `commit --onto-parent` you would skip `git post B && git merge 
B` steps, where "fixup commit" would be done with `--onto-parent B`, 
So you end up in situation like this:

 (2)  ...C  <- topic C
 |
...A |  <- topic A
\|
  ...o I'   <- integration
/|
...B---f |  <- topic B
 |
  ...D  <- topic D

State of index and working tree files in your F and my I' commit is 
exactly the same (I' = I + f), where in my case (2) history looks 
like "f" was part of topic B from the start, before integration 
merge happened.

BUT, all this said, I understand that your starting position, where 
not all topic branches are merged at the same time (possibly to keep 
conflict resolution sane), is probably more often to be encountered 
in real-life work... and as existing `--onto-parent` machinery should 
be able to support it already, I`m looking forward to make it happen :)

Once there, starting from your initial position:

>...A...C<- topics A, C
>\   \ E
>  ---o---o---o---o I<- integration <- HEAD
>/   /
>...B...D<- topics B, D

... and doing something like `git commit --onto B --merge` would yield:
 
 (3) ...A...C<- topics A, C
 \   \ E
   ---o---o---o---o I'   <- integration
 /   /|
 ...B...D |  <- topic D
 \|
  f---'  <- topic B

... where (I' = I + f) is still true. If that`s preferred in some 
cases, it could even look like this instead:

 (4) ...A...C <- topics A, C
 \   \ E  I
   ---o---o---o---o---F   <- integration
 /   /   /
 ...B...D   / <- topic D
 \ /
  f---'   <- topic B

... where F(4) = I'(3), so similar situation, just that we don`t 
discard I but post F on top of it.

Good thing is all necessary logic should already be in place, I just 
need to think a bit about the most sane user interface, and get back 
to you. Thanks for invaluable input so far :)

Of course, do feel free to drop any ideas you come up with as well, 
on how `git commit` user interface/options leading to (3) or (4) 
should look like (they could both be supported).

> > Like working on multiple branches at the same time, in the manner
> > similar to what `git add --patch` allows in regards to working on
> > multiple commits at the same time. This just takes it on yet another
> > level... hopefully :)
> 
> 'kay, I'm not eagerly waiting for this particular next level (I
> prefer to keep things plain and simple), but I would never say this
> were a broken workflow. ;)

Hehe, thanks, I guess :) Simplicity, but user-oriented, is the major 
point here, where you can work on unrelated patch series at the same 
time (patch queues?), without a need to switch branches, while you 
still 

Re: [SCRIPT/RFC 0/3] git-commit --onto-parent (three-way merge, no working tree file changes)

2017-11-29 Thread Johannes Sixt

Am 28.11.2017 um 02:15 schrieb Igor Djordjevic:

On 27/11/2017 22:54, Johannes Sixt wrote:


I my opinion, putting the focus on integration merge commits and the
desire to automate the re-merge step brings in a LOT of complexity in
the implementation for a very specific use-case that does not
necessarily help other cases.


It might seem more complex than it is, until you examine the guts to
see how it really works :)

Basic concept is pretty simple, as I actually don`t automate
anything, at least not in terms of what would manual user steps look
like - for example, there`s no real re-merge step in terms of
actually redoing the merge, I just reuse what was already there in a
very clean way, I would think (supported by my current, humble
knowledge, still).

The only merge that could possibly ever happen is upon committing
desired subset of changes onto parent, and that shouldn`t be too
complex by definition, otherwise that commit doesn`t really belong
there in the first place, if it can`t be meaningfully applied where
we want it (for now, at least).

That said, the whole operation of "posting on parent and re-merging
everything", the way it looks like from the outside, could end just
with a simple diff-apply-commit-commit internally, no merges at all.
Only if simple `git apply` fails, we try some trivial merging - and
all that inside separate (parent) index only, not touching original
HEAD index nor working tree, staying pristine for the whole process,
untouched.

Once done, you should be in the very same situation you started from,
nothing changed, just having your history tweaked a bit to tell a
different story on how you got there (now including a commit you
posted on your HEAD`s parent).


Ok, then please explain, how this process should work in my workflow and 
with the `commit --onto-parent` feature that you have in mind. I have an 
integration branch (which is a throw-away type, so you can mangle it in 
any way you want); it is a series of merges:


 ...A...C  <- topics A, C
 \   \
   ---o---o---o---o<- integration
 /   /
 ...B...D  <- topics B, D

Now I find a bug in topic B. Assume that the merges of C and D have 
textual conflicts with the integration branch (but not with B) and/or 
may be evil. What should I do?


With git-post, I make a fixup commit commit on the integration branch, 
then `git post B && git merge B`:


 ...A...C  <- topics A, C
 \   \
   ---o---o---o---o---f---F<- integration
 /   /   /
 ...B...D   /  <- topic D
 \ /
  f'--'<- topic B

The merge F does not introduce any changes on the integration branch, so 
I do not need it, but it helps keep topic B off radar when I ask `git 
branch --no-merged` later.



Don`t let "usual/preferred/recommended" Git workflow distract you too
much - one of the reasons I made this is because it also allows _kind
of_ "vanilla Git" patch queue, where you can quickly work on top of
the merge head, pushing commits onto parents below, being tips of
your "queues", putting you up to speed without a need to ever switch
a branch (hypothetically), until satisfied with what you have, where
you can slow down and polish each branch separately, as usual.

Like working on multiple branches at the same time, in the manner
similar to what `git add --patch` allows in regards to working on
multiple commits at the same time. This just takes it on yet another
level... hopefully :)


'kay, I'm not eagerly waiting for this particular next level (I prefer 
to keep things plain and simple), but I would never say this were a 
broken workflow. ;)



In your scenario above, it would certainly not be too bad if you
forgo the automatic merge and have the user issue a merge command
manually. The resulting history could look like this:

(3) o---o---A---X(topicA)
/ \   \
   /   M1--M2 (test, HEAD)
  /   /||
  ---o---o---M---' || (master)
  \   \   / |
   \   o-B /  (topicB)
\ /
 o---o---C(topicC)

I.e., commit --onto-parent A produced commit X, but M2 was then a
regular manual merge. (Of course, I am assuming that the merge
commits are dispensible, and only the resulting tree is of
interest.)


I see - and what you`re asking for is what I already envisioned and
hoped to get some more feedback about, here`s excerpt from
[SCRIPT/RFC 3/3] git-commit--onto-parent.sh[1] (I guess you didn`t
have time to checked that one yet?):


I did have a brief look, but I stopped when I saw

# Remove entry from HEAD reflog, not to pollute it with
# uninteresting in-between steps we take, leaking implementation
# details to end user.

It's a clear sign for me that's something wrong. It is not just reflogs 
that can become stale, but all operations that follow the `git commit` 
can 

Re: [SCRIPT/RFC 0/3] git-commit --onto-parent (three-way merge, no working tree file changes)

2017-11-27 Thread Igor Djordjevic
Hi Johannes,

On 27/11/2017 22:54, Johannes Sixt wrote:
> 
> I my opinion, putting the focus on integration merge commits and the
> desire to automate the re-merge step brings in a LOT of complexity in
> the implementation for a very specific use-case that does not
> necessarily help other cases.

It might seem more complex than it is, until you examine the guts to 
see how it really works :)

Basic concept is pretty simple, as I actually don`t automate 
anything, at least not in terms of what would manual user steps look 
like - for example, there`s no real re-merge step in terms of 
actually redoing the merge, I just reuse what was already there in a 
very clean way, I would think (supported by my current, humble 
knowledge, still).

The only merge that could possibly ever happen is upon committing 
desired subset of changes onto parent, and that shouldn`t be too 
complex by definition, otherwise that commit doesn`t really belong 
there in the first place, if it can`t be meaningfully applied where 
we want it (for now, at least).

That said, the whole operation of "posting on parent and re-merging 
everything", the way it looks like from the outside, could end just 
with a simple diff-apply-commit-commit internally, no merges at all. 
Only if simple `git apply` fails, we try some trivial merging - and 
all that inside separate (parent) index only, not touching original 
HEAD index nor working tree, staying pristine for the whole process, 
untouched.

Once done, you should be in the very same situation you started from, 
nothing changed, just having your history tweaked a bit to tell a 
different story on how you got there (now including a commit you 
posted on your HEAD`s parent).

Otherwise, I agree that explained use case might be a bit specific, 
but that is only because I recognized that one to be the most 
interesting to initially present (not to say one of more complex 
cases) - to me, at least, but it is certainly not the only one.

Don`t let "usual/preferred/recommended" Git workflow distract you too 
much - one of the reasons I made this is because it also allows _kind 
of_ "vanilla Git" patch queue, where you can quickly work on top of 
the merge head, pushing commits onto parents below, being tips of 
your "queues", putting you up to speed without a need to ever switch 
a branch (hypothetically), until satisfied with what you have, where 
you can slow down and polish each branch separately, as usual.

Like working on multiple branches at the same time, in the manner 
similar to what `git add --patch` allows in regards to working on 
multiple commits at the same time. This just takes it on yet another 
level... hopefully :)

> For example, in my daily work, I have encountered situations where,
> while working on one topic, I made a hot-fix for a different topic.
> There is no demand for a merge step in this scenario.
> 
> In your scenario above, it would certainly not be too bad if you
> forgo the automatic merge and have the user issue a merge command
> manually. The resulting history could look like this:
> 
> (3) o---o---A---X(topicA)
>/ \   \
>   /   M1--M2 (test, HEAD)
>  /   /||
>  ---o---o---M---' || (master)
>  \   \   / |
>   \   o-B /  (topicB)
>\ /
> o---o---C(topicC)
> 
> I.e., commit --onto-parent A produced commit X, but M2 was then a
> regular manual merge. (Of course, I am assuming that the merge
> commits are dispensible, and only the resulting tree is of
> interest.)

I see - and what you`re asking for is what I already envisioned and 
hoped to get some more feedback about, here`s excerpt from 
[SCRIPT/RFC 3/3] git-commit--onto-parent.sh[1] (I guess you didn`t 
have time to checked that one yet?):

  For example, it might make sense to separate commit creation (on 
  current HEAD`s parent) and its actual re-merging into integration 
  test branch, where "--remerge" (or something) parameter would be used 
  on top of "--onto-parent" to trigger both, if/when desired.
  
  Another direction to think in might be introducing more general 
  "--onto" parameter, too (or instead), without "parent" restriction, 
  allowing to record a commit on top of any arbitrary commit (other 
  than HEAD). This could even be defaulted to "git commit " 
  (no option needed), where current "git commit" behaviour would then 
  just be a special case of omitted  defaulting to HEAD, 
  aligning well with other Git commands sharing the same behaviour.

So I definitely look forward decoupling these two ((1) commit to 
parent and (2) remerge), with enough discussion flowing :)

Heck, even "to parent" is an artificial/imposed restriction now, in 
reality you could commit on top of any other commit you want (without 
switching branches)... but let`s take one step at a time.

Just note that omitting the remerge step is what actually makes the 
logic more complex, as we 

Re: [SCRIPT/RFC 0/3] git-commit --onto-parent (three-way merge, no working tree file changes)

2017-11-27 Thread Johannes Sixt

Am 26.11.2017 um 23:35 schrieb Igor Djordjevic:

Approach discussed here could have a few more useful applications,
but one seems to be standing out the most - in case where multiple
topic branches are temporarily merged for integration testing, it
could be very useful to be able to post "hotfix" commits to merged
branches directly, _without actually switching to them_ (and thus
without touching working tree files), and still keeping everything
merged, in one go.

Example starting point is "master" branch with 3 topic branches (A,
B, C), to be (throwaway) merged for integration testing inside
temporary "test" branch:

(1)o---o---A (topicA)
   /
  /
 /
 ---o---o---M (master, test, HEAD)
 \   \
  \   o---B (topicB)
   \
o---o---C (topicC)


This is what we end up with once "master" and topic branches are
merged in merge commit M1 inside temporary "test" branch for further
integration testing:

(2)o---o---A (topicA)
   / \
  /   M1 (test, HEAD)
 /   /||
 ---o---o---M---/ || (master)
 \   \   / |
  \   o---B-/  | (topicB)
   \   |
o---o---C--/ (topicC)


Upon discovery of a fix needed inside "topicA", hotfix changes X
should be committed to "topicA" branch and re-merged inside merge
commit M2 on temporary integration "test" branch (previous temporary
merge commit M1 is thrown away as uninteresting):

(3)o---o---A---X (topicA)
   / \
  /   M2 (test, HEAD)
 /   /||
 ---o---o---M---/ || (master)
 \   \   / |
  \   o---B-/  | (topicB)
   \  /
o---o---C/ (topicC)


I my opinion, putting the focus on integration merge commits and the 
desire to automate the re-merge step brings in a LOT of complexity in 
the implementation for a very specific use-case that does not 
necessarily help other cases.


For example, in my daily work, I have encountered situations where, 
while working on one topic, I made a hot-fix for a different topic. 
There is no demand for a merge step in this scenario.


In your scenario above, it would certainly not be too bad if you forgo 
the automatic merge and have the user issue a merge command manually. 
The resulting history could look like this:


(3) o---o---A---X(topicA)
   / \   \
  /   M1--M2 (test, HEAD)
 /   /||
 ---o---o---M---' || (master)
 \   \   / |
  \   o-B /  (topicB)
   \ /
o---o---C(topicC)

I.e., commit --onto-parent A produced commit X, but M2 was then a 
regular manual merge. (Of course, I am assuming that the merge commits 
are dispensible, and only the resulting tree is of interest.)


Moreover, you seem to assume that an integration branch is an octopus 
merge, that can be re-created easily. I would say that this a very, very 
exceptional situation.




At this point, I spent five minutes thinking of how I would use commit 
--onto-parent if I did not have git-post.


While on the integration branch, I typically make separate commits for 
each fix, mostly because the bugs are discovered and fixed not 
simultaneously, but over time. So, I have a small number of commits that 
I distribute later using my git-post script. But that does not have to 
be so. I think I could work with a git commit --onto-parent feature as 
long as it does not attempt to make a merge commit for me. (I would hate 
that.)


Sometimes, however I have two bug fixes in the worktree, ready to be 
committed. Then the ability to pass pathspec to git commit is useful. 
Does your implementation support this use case (partially staged 
worktree changes)?


Thanks,
-- Hannes