splitting a commit that adds new files

5 messages, 2 authors, 2016-06-15 · open the first message on its own page

splitting a commit that adds new files

From: Duy Nguyen <hidden>
Date: 2016-06-15 22:59:47

I usually start splitting a commit with "reset @^" then "add -p" back.
The problem is "reset @^" does not keep track of new files added in
HEAD, so I often end up forgetting to add new files back (with "add
-p"). I'm thinking of making "reset" to do "add -N" automatically for
me so I won't miss changes in "add -p". But maybe people already know
how to deal with this case without adding more code?
-- 
Duy

[PATCH 1/2] t7101, t7014: rename test files to indicate what that file is for

From: Nguyễn Thái Ngọc Duy <hidden>
Date: 2016-06-15 22:59:49

Signed-off-by: Nguyễn Thái Ngọc Duy <redacted>
---
 Looks like a good thing to do.. Three files with the same "-reset.sh"
 suffix could be confusing.

 t/t7101-reset-empty-subdirs.sh (new +x) | 63 +++++++++++++++++++++++++++++++++
 t/t7101-reset.sh (gone)                 | 63 ---------------------------------
 t/t7104-reset-hard.sh (new +x)          | 46 ++++++++++++++++++++++++
 t/t7104-reset.sh (gone)                 | 46 ------------------------
 4 files changed, 109 insertions(+), 109 deletions(-)
 create mode 100755 t/t7101-reset-empty-subdirs.sh
 delete mode 100755 t/t7101-reset.sh
 create mode 100755 t/t7104-reset-hard.sh
 delete mode 100755 t/t7104-reset.sh
diff --git a/t/t7101-reset-empty-subdirs.sh b/t/t7101-reset-empty-subdirs.sh
new file mode 100755
index 0000000..96e163f
--- /dev/null
+++ b/t/t7101-reset-empty-subdirs.sh
@@ -0,0 +1,63 @@
+#!/bin/sh
+#
+# Copyright (c) 2006 Shawn Pearce
+#
+
+test_description='git reset should cull empty subdirs'
+. ./test-lib.sh
+
+test_expect_success \
+    'creating initial files' \
+    'mkdir path0 &&
+     cp "$TEST_DIRECTORY"/../COPYING path0/COPYING &&
+     git add path0/COPYING &&
+     git commit -m add -a'
+
+test_expect_success \
+    'creating second files' \
+    'mkdir path1 &&
+     mkdir path1/path2 &&
+     cp "$TEST_DIRECTORY"/../COPYING path1/path2/COPYING &&
+     cp "$TEST_DIRECTORY"/../COPYING path1/COPYING &&
+     cp "$TEST_DIRECTORY"/../COPYING COPYING &&
+     cp "$TEST_DIRECTORY"/../COPYING path0/COPYING-TOO &&
+     git add path1/path2/COPYING &&
+     git add path1/COPYING &&
+     git add COPYING &&
+     git add path0/COPYING-TOO &&
+     git commit -m change -a'
+
+test_expect_success \
+    'resetting tree HEAD^' \
+    'git reset --hard HEAD^'
+
+test_expect_success \
+    'checking initial files exist after rewind' \
+    'test -d path0 &&
+     test -f path0/COPYING'
+
+test_expect_success \
+    'checking lack of path1/path2/COPYING' \
+    '! test -f path1/path2/COPYING'
+
+test_expect_success \
+    'checking lack of path1/COPYING' \
+    '! test -f path1/COPYING'
+
+test_expect_success \
+    'checking lack of COPYING' \
+    '! test -f COPYING'
+
+test_expect_success \
+    'checking checking lack of path1/COPYING-TOO' \
+    '! test -f path0/COPYING-TOO'
+
+test_expect_success \
+    'checking lack of path1/path2' \
+    '! test -d path1/path2'
+
+test_expect_success \
+    'checking lack of path1' \
+    '! test -d path1'
+
+test_done
diff --git a/t/t7101-reset.sh b/t/t7101-reset.sh
deleted file mode 100755
index 96e163f..0000000
--- a/t/t7101-reset.sh
+++ /dev/null
@@ -1,63 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2006 Shawn Pearce
-#
-
-test_description='git reset should cull empty subdirs'
-. ./test-lib.sh
-
-test_expect_success \
-    'creating initial files' \
-    'mkdir path0 &&
-     cp "$TEST_DIRECTORY"/../COPYING path0/COPYING &&
-     git add path0/COPYING &&
-     git commit -m add -a'
-
-test_expect_success \
-    'creating second files' \
-    'mkdir path1 &&
-     mkdir path1/path2 &&
-     cp "$TEST_DIRECTORY"/../COPYING path1/path2/COPYING &&
-     cp "$TEST_DIRECTORY"/../COPYING path1/COPYING &&
-     cp "$TEST_DIRECTORY"/../COPYING COPYING &&
-     cp "$TEST_DIRECTORY"/../COPYING path0/COPYING-TOO &&
-     git add path1/path2/COPYING &&
-     git add path1/COPYING &&
-     git add COPYING &&
-     git add path0/COPYING-TOO &&
-     git commit -m change -a'
-
-test_expect_success \
-    'resetting tree HEAD^' \
-    'git reset --hard HEAD^'
-
-test_expect_success \
-    'checking initial files exist after rewind' \
-    'test -d path0 &&
-     test -f path0/COPYING'
-
-test_expect_success \
-    'checking lack of path1/path2/COPYING' \
-    '! test -f path1/path2/COPYING'
-
-test_expect_success \
-    'checking lack of path1/COPYING' \
-    '! test -f path1/COPYING'
-
-test_expect_success \
-    'checking lack of COPYING' \
-    '! test -f COPYING'
-
-test_expect_success \
-    'checking checking lack of path1/COPYING-TOO' \
-    '! test -f path0/COPYING-TOO'
-
-test_expect_success \
-    'checking lack of path1/path2' \
-    '! test -d path1/path2'
-
-test_expect_success \
-    'checking lack of path1' \
-    '! test -d path1'
-
-test_done
diff --git a/t/t7104-reset-hard.sh b/t/t7104-reset-hard.sh
new file mode 100755
index 0000000..f136ee7
--- /dev/null
+++ b/t/t7104-reset-hard.sh
@@ -0,0 +1,46 @@
+#!/bin/sh
+
+test_description='reset --hard unmerged'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+
+	mkdir before later &&
+	>before/1 &&
+	>before/2 &&
+	>hello &&
+	>later/3 &&
+	git add before hello later &&
+	git commit -m world &&
+
+	H=$(git rev-parse :hello) &&
+	git rm --cached hello &&
+	echo "100644 $H 2	hello" | git update-index --index-info &&
+
+	rm -f hello &&
+	mkdir -p hello &&
+	>hello/world &&
+	test "$(git ls-files -o)" = hello/world
+
+'
+
+test_expect_success 'reset --hard should restore unmerged ones' '
+
+	git reset --hard &&
+	git ls-files --error-unmatch before/1 before/2 hello later/3 &&
+	test -f hello
+
+'
+
+test_expect_success 'reset --hard did not corrupt index nor cached-tree' '
+
+	T=$(git write-tree) &&
+	rm -f .git/index &&
+	git add before hello later &&
+	U=$(git write-tree) &&
+	test "$T" = "$U"
+
+'
+
+test_done
diff --git a/t/t7104-reset.sh b/t/t7104-reset.sh
deleted file mode 100755
index f136ee7..0000000
--- a/t/t7104-reset.sh
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/bin/sh
-
-test_description='reset --hard unmerged'
-
-. ./test-lib.sh
-
-test_expect_success setup '
-
-	mkdir before later &&
-	>before/1 &&
-	>before/2 &&
-	>hello &&
-	>later/3 &&
-	git add before hello later &&
-	git commit -m world &&
-
-	H=$(git rev-parse :hello) &&
-	git rm --cached hello &&
-	echo "100644 $H 2	hello" | git update-index --index-info &&
-
-	rm -f hello &&
-	mkdir -p hello &&
-	>hello/world &&
-	test "$(git ls-files -o)" = hello/world
-
-'
-
-test_expect_success 'reset --hard should restore unmerged ones' '
-
-	git reset --hard &&
-	git ls-files --error-unmatch before/1 before/2 hello later/3 &&
-	test -f hello
-
-'
-
-test_expect_success 'reset --hard did not corrupt index nor cached-tree' '
-
-	T=$(git write-tree) &&
-	rm -f .git/index &&
-	git add before hello later &&
-	U=$(git write-tree) &&
-	test "$T" = "$U"
-
-'
-
-test_done
-- 
1.8.5.2.240.g8478abd

[PATCH 2/2] reset: support "--mixed --intent-to-add" mode

From: Nguyễn Thái Ngọc Duy <hidden>
Date: 2016-06-15 22:59:49

When --mixed is used, entries could be removed from index if the
target ref does not have them. When "reset" is used in preparation for
commit spliting (in a dirty worktree), it could be hard to track what
files to be added back. The new option --intent-to-add simplifies it
by marking all removed files intent-to-add.

Signed-off-by: Nguyễn Thái Ngọc Duy <redacted>
---
 Documentation/git-reset.txt |  5 ++++-
 builtin/reset.c             | 19 +++++++++++++++++--
 cache.h                     |  1 +
 read-cache.c                |  9 +++++++++
 t/t7102-reset.sh            |  9 +++++++++
 5 files changed, 40 insertions(+), 3 deletions(-)
diff --git a/Documentation/git-reset.txt b/Documentation/git-reset.txt
index f445cb3..a077ba0 100644
--- a/Documentation/git-reset.txt
+++ b/Documentation/git-reset.txt
@@ -10,7 +10,7 @@ SYNOPSIS
 [verse]
 'git reset' [-q] [<tree-ish>] [--] <paths>...
 'git reset' (--patch | -p) [<tree-ish>] [--] [<paths>...]
-'git reset' [--soft | --mixed | --hard | --merge | --keep] [-q] [<commit>]
+'git reset' [--soft | --mixed [-N] | --hard | --merge | --keep] [-q] [<commit>]
 
 DESCRIPTION
 -----------
@@ -60,6 +60,9 @@ section of linkgit:git-add[1] to learn how to operate the `--patch` mode.
 	Resets the index but not the working tree (i.e., the changed files
 	are preserved but not marked for commit) and reports what has not
 	been updated. This is the default action.
++
+If `-N` is specified, removed paths are marked as intent-to-add (see
+linkgit:git-add[1]).
 
 --hard::
 	Resets the index and working tree. Any changes to tracked files in the
diff --git a/builtin/reset.c b/builtin/reset.c
index 6004803..f34eab4 100644
--- a/builtin/reset.c
+++ b/builtin/reset.c
@@ -116,6 +116,7 @@ static void update_index_from_diff(struct diff_queue_struct *q,
 		struct diff_options *opt, void *data)
 {
 	int i;
+	int *intent_to_add = data;
 
 	for (i = 0; i < q->nr; i++) {
 		struct diff_filespec *one = q->queue[i]->one;
@@ -128,13 +129,20 @@ static void update_index_from_diff(struct diff_queue_struct *q,
 				    one->path);
 			add_cache_entry(ce, ADD_CACHE_OK_TO_ADD |
 				ADD_CACHE_OK_TO_REPLACE);
+		} else if (*intent_to_add) {
+			int pos = cache_name_pos(one->path, strlen(one->path));
+			if (pos < 0)
+				die(_("%s does not exist in index"),
+				    one->path);
+			set_intent_to_add(&the_index, active_cache[pos]);
 		} else
 			remove_file_from_cache(one->path);
 	}
 }
 
 static int read_from_tree(const struct pathspec *pathspec,
-			  unsigned char *tree_sha1)
+			  unsigned char *tree_sha1,
+			  int intent_to_add)
 {
 	struct diff_options opt;
 
@@ -142,6 +150,7 @@ static int read_from_tree(const struct pathspec *pathspec,
 	copy_pathspec(&opt.pathspec, pathspec);
 	opt.output_format = DIFF_FORMAT_CALLBACK;
 	opt.format_callback = update_index_from_diff;
+	opt.format_callback_data = &intent_to_add;
 
 	if (do_diff_cache(tree_sha1, &opt))
 		return 1;
@@ -258,6 +267,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 	const char *rev;
 	unsigned char sha1[20];
 	struct pathspec pathspec;
+	int intent_to_add = 0;
 	const struct option options[] = {
 		OPT__QUIET(&quiet, N_("be quiet, only report errors")),
 		OPT_SET_INT(0, "mixed", &reset_type,
@@ -270,6 +280,8 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 		OPT_SET_INT(0, "keep", &reset_type,
 				N_("reset HEAD but keep local changes"), KEEP),
 		OPT_BOOL('p', "patch", &patch_mode, N_("select hunks interactively")),
+		OPT_BOOL('N', "intent-to-add", &intent_to_add,
+				N_("record only the fact that removed paths will be added later")),
 		OPT_END()
 	};
 
@@ -327,6 +339,9 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 		die(_("%s reset is not allowed in a bare repository"),
 		    _(reset_type_names[reset_type]));
 
+	if (intent_to_add && reset_type != MIXED)
+		die(_("-N can only be used with --mixed"));
+
 	/* Soft reset does not touch the index file nor the working tree
 	 * at all, but requires them in a good order.  Other resets reset
 	 * the index file to the tree object we are switching to. */
@@ -338,7 +353,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 		int newfd = hold_locked_index(lock, 1);
 		if (reset_type == MIXED) {
 			int flags = quiet ? REFRESH_QUIET : REFRESH_IN_PORCELAIN;
-			if (read_from_tree(&pathspec, sha1))
+			if (read_from_tree(&pathspec, sha1, intent_to_add))
 				return 1;
 			refresh_index(&the_index, flags, NULL, NULL,
 				      _("Unstaged changes after reset:"));
diff --git a/cache.h b/cache.h
index dc040fb..9d5e09e 100644
--- a/cache.h
+++ b/cache.h
@@ -479,6 +479,7 @@ extern void rename_index_entry_at(struct index_state *, int pos, const char *new
 extern int remove_index_entry_at(struct index_state *, int pos);
 extern void remove_marked_cache_entries(struct index_state *istate);
 extern int remove_file_from_index(struct index_state *, const char *path);
+extern int set_intent_to_add(struct index_state *, struct cache_entry *);
 #define ADD_CACHE_VERBOSE 1
 #define ADD_CACHE_PRETEND 2
 #define ADD_CACHE_IGNORE_ERRORS	4
diff --git a/read-cache.c b/read-cache.c
index 33dd676..dc160a3 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -587,6 +587,15 @@ static void record_intent_to_add(struct cache_entry *ce)
 	hashcpy(ce->sha1, sha1);
 }
 
+int set_intent_to_add(struct index_state *istate, struct cache_entry *ce)
+{
+	record_intent_to_add(ce);
+	ce->ce_flags |= CE_INTENT_TO_ADD;
+	cache_tree_invalidate_path(istate->cache_tree, ce->name);
+	istate->cache_changed = 1;
+	return 0;
+}
+
 int add_to_index(struct index_state *istate, const char *path, struct stat *st, int flags)
 {
 	int size, namelen, was_same;
diff --git a/t/t7102-reset.sh b/t/t7102-reset.sh
index 8d4b50d..642920a 100755
--- a/t/t7102-reset.sh
+++ b/t/t7102-reset.sh
@@ -535,4 +535,13 @@ test_expect_success 'reset with paths accepts tree' '
 	git diff HEAD --exit-code
 '
 
+test_expect_success 'reset -N keeps removed files as intent-to-add' '
+	echo new-file >new-file &&
+	git add new-file &&
+	git reset -N HEAD &&
+	git diff --name-only >actual &&
+	echo new-file >expect &&
+	test_cmp expect actual
+'
+
 test_done
-- 
1.8.5.2.240.g8478abd

Re: [PATCH 1/2] t7101, t7014: rename test files to indicate what that file is for

From: Jonathan Nieder <hidden>
Date: 2016-06-15 22:59:49

Nguyễn Thái Ngọc Duy wrote:
Signed-off-by: Nguyễn Thái Ngọc Duy <redacted>
Makes sense.

[...]
 t/t7101-reset-empty-subdirs.sh (new +x) | 63 +++++++++++++++++++++++++++++++++
 t/t7101-reset.sh (gone)                 | 63 ---------------------------------
 t/t7104-reset-hard.sh (new +x)          | 46 ++++++++++++++++++++++++
 t/t7104-reset.sh (gone)                 | 46 ------------------------
Hm, summary incorporated in the diffstat.  Neat. :)

format-patch -M tells me that this indeed just renamed the files, so
fwiw

Reviewed-by: Jonathan Nieder <redacted>

Re: [PATCH 1/2] t7101, t7014: rename test files to indicate what that file is for

From: Duy Nguyen <hidden>
Date: 2016-06-15 22:59:50

On Tue, Feb 4, 2014 at 11:05 PM, Jonathan Nieder [off-list ref] wrote:
quoted
 t/t7101-reset-empty-subdirs.sh (new +x) | 63 +++++++++++++++++++++++++++++++++
 t/t7101-reset.sh (gone)                 | 63 ---------------------------------
 t/t7104-reset-hard.sh (new +x)          | 46 ++++++++++++++++++++++++
 t/t7104-reset.sh (gone)                 | 46 ------------------------
Hm, summary incorporated in the diffstat.  Neat. :)
Yeah, it's from this patch [1]. Maybe I should give it another push,
then remove --summary from format-patch diffstat.

[1] http://article.gmane.org/gmane.comp.version-control.git/213752
-- 
Duy
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help