git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Junio C Hamano <junkio@cox.net>
To: Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
Cc: git@vger.kernel.org, Johannes Schindelin <Johannes.Schindelin@gmx.de>
Subject: Re: [PATCH] git-add --interactive (wip)
Date: Tue, 12 Dec 2006 13:51:49 -0800	[thread overview]
Message-ID: <7vwt4wpytm.fsf@assigned-by-dhcp.cox.net> (raw)
In-Reply-To: <200612111147.44964.Josef.Weidendorfer@gmx.de> (Josef Weidendorfer's message of "Mon, 11 Dec 2006 11:47:44 +0100")

Josef Weidendorfer <Josef.Weidendorfer@gmx.de> writes:

> I just tried to work with this thing to separate my recent
> "branch.*.localmerge" changes to the simple version I posted
> afterwards.
>
> I noted that I need to manually change a few dependent hunks,
> so this "one hunk at a time" and not being able to edit changes
> in a hunk does not fit my workflow.

I've updated my "git add --interactive" in 'pu' and it now knows
how to split a hunk into smaller pieces and recounting the diff
offsets before applying (Johannes pointed out that his partial
commit script, entirely written in bash using shell arrays, has
a similar feature.  I guess I should have stolen his code
instead of lifting the logic from my own abandoned porcelain).

Hunk splitting allows you to start with this hunk:

        @@ -9,9 +9,10 @@
         #include "builtin.h"
         #include "dir.h"
         #include "cache-tree.h"
        +#include "exec_cmd.h"

         static const char builtin_add_usage[] =
        -"git-add [-n] [-v] <filepattern>...";
        +"git-add [-n] [-v] <filepattern>... | git-add --interactive";

         static void prune_directory(struct dir_struct *dir, const char **...
         {

and lets you split it into two, and you can pick each individually:

        @@ -9,5 +9,6 @@
         #include "builtin.h"
         #include "dir.h"
         #include "cache-tree.h"
        +#include "exec_cmd.h"

         static const char builtin_add_usage[] =
        @@ -12,6 +13,6 @@

         static const char builtin_add_usage[] =
        -"git-add [-n] [-v] <filepattern>...";
        +"git-add [-n] [-v] <filepattern>... | git-add --interactive";

         static void prune_directory(struct dir_struct *dir, const char **...
         {

The post-context of the first hunk and pre-context of the
second hunk are duplicated to give you better context when
reviewing each of them alone.  If you choose to apply both, they
are merged back again before applied.

Anyway, after I finished doing this, I started thinking...

One of the most beautifully done patch series in git.git history
is this series by Sergey Vlasov:

	http://thread.gmane.org/gmane.comp.version-control.git/9057

The resulting commits are from e8d2a6d4 to 4041483e (inclusive).

What's interesting about this series is that its patches touch
the same area of the code over and over again, refining a bit by
bit as the series progresses.

Sergey might have done it exactly the way the final patches
presented the evolution, but I somehow doubt it [*1*].  I often
have the state that corresponds to [PATCH n/n] in my working
tree after hacking around without making a single commit, and
often would start wanting to commit the state as a clean
multi-step series at that point.  I think this is the same for
everybody.

What I often end up doing is to make a snapshot of that
"proposed final" state, reset to the original, and work toward
the proposed final state:

	# snapshot
	$ git commit -a -m 'commit goal'
        $ git tag -f CG
        $ git reset --hard HEAD^

	# repeat for (i = 1; i <= n; i++)
        $ git diff HEAD CG >P.diff
        $ edit
        # use P.diff as a reference, and edit the working tree
        # files to produce [i/n] state.  I might remove pieces
        # that belong to [j/n] for j > i from  P.diff and run
	# "git apply --index", or hand edit the files directly
	# in the working tree.
	$ make test
        $ git commit -a -m "[PATCH i/n] title..."
        # end repeat

	# when finished the above cycle, this diff should only
	# show the improvements I made during the decomposition.
        $ git diff CG HEAD

For a very simple case where the patch munging in the "repeat"
part of the above workflow only deletes hunks (or sub-hunks),
the patch subcommand of "git add --interactive" with hunk
splitting would work nicely, but in general it would not be
enough.  It certainly is far from usable to produce something
like what Sergey gave us.

To make it easier, one possibility might be to add a subcommand
to "git add --interactive" that lets you edit what is currently
staged in the index by opening a temporary copy in your favorite
editor, and stage the result of your edit in the index.  But I
feel quite uneasy to introduce ways to update the index with
something _wildly_ different from what you ever had in your
working tree as a whole.

I think it is wrong to commit partially, purely from the index,
when you are building a series that has complex changes that
come during the series but go away at the end.  The user should
be able to verify all the steps in the middle in such a complex
series, but it is not easy if you have it only in the index.

You could do

	$ git checkout-index --prefix=testarea/ -f -q -u -a

and run your tests there, but that takes a discipline, and is
cumbersome to do.

So in short, I think per-hunk update-index is a cute hack and
may be useful in a narrow simple cases, but it would not be so
useful in the real life.


> Just as a sidenote: after deciding to not apply hunks, you
> lose them in this WIP, as you will find nothing in "unstaged" mode
> afterwards :-(

I do not understand this part.  You can 'revert' to match the
index to HEAD and run 'patch' to pick what you want again.


[Footnote]

*1* Maybe Sergey indeed did things the way the series was
presented, in which case that would only strengthen my respect
to his ability even more.  The quoted patch series made him one
of three people on the git list whose patches I trust 100%; in
fact, I trust their patches so much that I read them not to find
bugs but to admire and enjoy.

  reply	other threads:[~2006-12-12 21:51 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-12-08 12:36 git-commit: select which files to commit while editing the commit message Pazu
2006-12-08 19:18 ` Junio C Hamano
2006-12-08 19:32   ` Jakub Narebski
2006-12-08 20:45     ` Luben Tuikov
2006-12-08 22:10       ` Josef Weidendorfer
2006-12-08 23:59         ` Seth Falcon
2006-12-09  0:07           ` Jakub Narebski
2006-12-09  0:37             ` Seth Falcon
2006-12-09  0:59               ` Junio C Hamano
2006-12-10  0:46                 ` Josef Weidendorfer
2006-12-10  0:54                   ` Junio C Hamano
2006-12-11  9:23                     ` [PATCH] git-add --interactive (wip) Junio C Hamano
2006-12-11 10:47                       ` Josef Weidendorfer
2006-12-12 21:51                         ` Junio C Hamano [this message]
2006-12-12 22:15                           ` Johannes Schindelin
2006-12-13  9:20                             ` Andreas Ericsson
2006-12-13  3:15                           ` Josef Weidendorfer
2006-12-13  5:34                             ` Junio C Hamano
2006-12-13 10:42                               ` Johannes Schindelin
2006-12-13 10:57                                 ` Shawn Pearce
2006-12-13 11:20                                   ` Johannes Schindelin
2006-12-13 20:31                               ` Josef Weidendorfer
2006-12-09  7:02   ` git-commit: select which files to commit while editing the commit message Sean

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=7vwt4wpytm.fsf@assigned-by-dhcp.cox.net \
    --to=junkio@cox.net \
    --cc=Johannes.Schindelin@gmx.de \
    --cc=Josef.Weidendorfer@gmx.de \
    --cc=git@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).