With "git add -e [<files>]", Git will fire up an editor with the current diff relative to the index (i.e. what you would get with "git diff [<files>]"). Now you can edit the patch as much as you like, including adding/removing lines, editing the text, whatever. Make sure, though, that the first character of the hunk lines is still a space, a plus or a minus. After you closed the editor, Git will adjust the line counts of the hunks if necessary, thanks to the --fixup-line-counts option of apply, and commit the patch. Except if you deleted everything, in which case nothing happens (for obvious reasons). Signed-off-by: Johannes Schindelin <johannes.schindelin@xxxxxx> --- This was too useful to let slip by. I even committed it using "git add -e <files>" several times! Anyway, bed time. Documentation/git-add.txt | 9 ++++++- builtin-add.c | 49 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt index 1afd0c6..dd744f1 100644 --- a/Documentation/git-add.txt +++ b/Documentation/git-add.txt @@ -8,8 +8,8 @@ git-add - Add file contents to the index SYNOPSIS -------- [verse] -'git-add' [-n] [-v] [-f] [--interactive | -i] [--patch | -p] [-u] [--refresh] - [--ignore-errors] [--] <filepattern>... +'git-add' [-n] [-v] [-f] [--interactive | -i] [--patch | -p] [--edit | -e] + [-u] [--refresh] [--ignore-errors] [--] <filepattern>... DESCRIPTION ----------- @@ -70,6 +70,11 @@ OPTIONS bypassed and the 'patch' subcommand is invoked using each of the specified filepatterns before exiting. +-e, \--edit:: + Open the diff vs. the index in an editor and let the user + edit it. After the editor was closed, adjust the hunk headers + and apply the patch to the index. + -u:: Update only files that git already knows about, staging modified content for commit and marking deleted files for removal. This diff --git a/builtin-add.c b/builtin-add.c index 1da22ee..05ae40d 100644 --- a/builtin-add.c +++ b/builtin-add.c @@ -19,7 +19,7 @@ static const char * const builtin_add_usage[] = { "git-add [options] [--] <filepattern>...", NULL }; -static int patch_interactive = 0, add_interactive = 0; +static int patch_interactive = 0, add_interactive = 0, edit_interactive = 0; static int take_worktree_changes; static void prune_directory(struct dir_struct *dir, const char **pathspec, int prefix) @@ -186,6 +186,50 @@ int interactive_add(int argc, const char **argv, const char *prefix) return status; } +int edit_patch(int argc, const char **argv, const char *prefix) +{ + static struct lock_file lock; + struct child_process child; + int ac; + struct stat st; + + memset(&child, 0, sizeof(child)); + child.argv = xcalloc(sizeof(const char *), (argc + 5)); + ac = 0; + child.git_cmd = 1; + child.argv[ac++] = "diff-files"; + child.argv[ac++] = "--no-color"; + child.argv[ac++] = "-p"; + child.argv[ac++] = "--"; + if (argc) { + const char **pathspec = validate_pathspec(argc, argv, prefix); + if (!pathspec) + return -1; + memcpy(&(child.argv[ac]), pathspec, sizeof(*argv) * argc); + ac += argc; + } + child.argv[ac] = NULL; + child.out = hold_lock_file_for_update(&lock, git_path("EDIT_PATCH"), 1); + + if (run_command(&child)) + return 1; + free(child.argv); + + launch_editor(lock.filename, NULL, NULL); + + if (stat(lock.filename, &st)) + return 1; + if (!st.st_size) { + fprintf(stderr, "Empty patch. Aborted.\n"); + return 0; + } + + execl_git_cmd("apply", "--fixup-line-counts", "--cached", + lock.filename, NULL); + + return 1; +} + static struct lock_file lock_file; static const char ignore_error[] = @@ -200,6 +244,7 @@ static struct option builtin_add_options[] = { OPT_GROUP(""), OPT_BOOLEAN('i', "interactive", &add_interactive, "interactive picking"), OPT_BOOLEAN('p', "patch", &patch_interactive, "interactive patching"), + OPT_BOOLEAN('e', "edit", &edit_interactive, "super-interactive patching"), OPT_BOOLEAN('f', NULL, &ignored_too, "allow adding otherwise ignored files"), OPT_BOOLEAN('u', NULL, &take_worktree_changes, "update tracked files"), OPT_BOOLEAN( 0 , "refresh", &refresh_only, "don't add, only refresh the index"), @@ -226,6 +271,8 @@ int cmd_add(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, builtin_add_options, builtin_add_usage, 0); + if (edit_interactive) + return(edit_patch(argc, argv, prefix)); if (patch_interactive) add_interactive = 1; if (add_interactive) -- 1.5.6.rc1.181.gb439d -- 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