* committing selected 'changed' or 'added' files works, but not 'removed'
@ 2007-05-14 6:16 Jim Meyering
2007-05-14 7:44 ` Junio C Hamano
0 siblings, 1 reply; 3+ messages in thread
From: Jim Meyering @ 2007-05-14 6:16 UTC (permalink / raw)
To: git
Hello,
If I've just run "git-rm -f c" in a directory with a few modified
or git-added files, is there some way to commit (non-interactively)
only the removal of that selected file? I.e., not any other changes
in the working directory? git-commit -m. -- c fails with this:
error: pathspec 'c' did not match any file(s) known to git
If I use "cg-commit" instead of "git-commit", it works fine.
When I asked on IRC, "cehteh" suggested to create a temporary branch,
do the removal there, and then to rebase that change back onto the
original branch -- and to remove the disposable branch. Yes, that works,
but I want do the job with a single commit command, the same way I can
for "added" and "modified" files. And I've been trying (until now,
successfully) to wean myself away from cogito.
Why should "removed" files be handled so differently? If I cannot commit
a selected "file removal" (regardless of the state of the index), then
isn't that an opportunity to add a feature?
In case you're wondering, I want this functionality in order to make
a version control agnostic commit/diff/ChangeLog tool work the same way
with raw git as it did using cogito.
-------------------------------------------
In case an actual scenario helps, I'd like to be able to commit the
removal of "c", below without also committing the change to "b":
mkdir .j && cd .j && git-init > /dev/null && touch b c && git-add b c \
&& git-commit -q -m. && echo > b && git-rm --quiet -f c \
&& git-commit -m. -- c
The final commit above fails like this:
error: pathspec 'c' did not match any file(s) known to git.
Did you forget to 'git add'?
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: committing selected 'changed' or 'added' files works, but not 'removed'
2007-05-14 6:16 committing selected 'changed' or 'added' files works, but not 'removed' Jim Meyering
@ 2007-05-14 7:44 ` Junio C Hamano
2007-05-14 12:48 ` Jim Meyering
0 siblings, 1 reply; 3+ messages in thread
From: Junio C Hamano @ 2007-05-14 7:44 UTC (permalink / raw)
To: Jim Meyering; +Cc: git
Jim Meyering <jim@meyering.net> writes:
> Why should "removed" files be handled so differently? If I cannot commit
> a selected "file removal" (regardless of the state of the index), then
> isn't that an opportunity to add a feature?
The answer is because it is a bit cumbersome to arrange, and
people who felt the need were too lazy to add that. And
everybody knows that I am not from the "partial commit" camp.
You could do something like this...
NOTE NOTE NOTE.
I am not quite happy with this one, as it exposes one of my
favorite pet peeves -- wildcard pathspecs behave differently
between diff-tree family and ls-files family. After modifying a
random C source file, you can say:
git commit -m 'C files changed' -- '*.c'
but you cannot say:
git commit -m 'C files modified and/or removed' -- '*.c'
after removing a C source file, because diff-tree's pathspec
only works as top-down, subdirectory limiter.
-- >8 --
git-commit: Allow removal to be partially committed as well
We allow partial commit of modified and added files but never
handled removed files. This hacks it around.
Signed-off-by: Junio C Hamano <junkio@cox.net>
---
git-commit.sh | 36 ++++++++++++++++++++++++++++++-
t/t7400-commit.sh | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 95 insertions(+), 1 deletions(-)
diff --git a/git-commit.sh b/git-commit.sh
index f28fc24..f4ba0ef 100755
--- a/git-commit.sh
+++ b/git-commit.sh
@@ -59,6 +59,40 @@ run_status () {
${untracked_files:+--untracked}
}
+compute_commit_only () {
+
+ # The first one cannot commit removal
+ if test -n "$initial_commit"
+ then
+ exec git-ls-files --error-unmatch -- "$@"
+ fi
+
+ # Usual case -- no unmatch
+ if files=$(git-ls-files --error-unmatch -- "$@" 2>/dev/null)
+ then
+ echo "$files"
+ exit 0
+ fi
+
+ has_unmatch_errs=
+ # Otherwise we need to do it the hard way
+ for p in "$@"
+ do
+ removed=$(git-diff-index --cached --name-only \
+ --diff-filter=D HEAD -- "$p")
+ if test -n "$removed"
+ then
+ echo "$removed"
+ elif git-ls-files --error-unmatch -- "$p"
+ then
+ : ok so far
+ else
+ has_unmatch_errs=t
+ fi
+ done
+ test -z "$has_unmatch_errs"
+}
+
trap '
test -z "$TMP_INDEX" || {
test -f "$TMP_INDEX" && rm -f "$TMP_INDEX"
@@ -364,7 +398,7 @@ t,)
refuse_partial "Cannot do a partial commit during a merge."
fi
TMP_INDEX="$GIT_DIR/tmp-index$$"
- commit_only=`git-ls-files --error-unmatch -- "$@"` || exit
+ commit_only=$( (compute_commit_only "$@") ) || exit
# Build a temporary index and update the real index
# the same way.
diff --git a/t/t7400-commit.sh b/t/t7400-commit.sh
new file mode 100755
index 0000000..81196b0
--- /dev/null
+++ b/t/t7400-commit.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+
+test_description='git commit porcelain-ish'
+
+. ./test-lib.sh
+
+test_expect_success 'the basics' '
+
+ echo doing partial >"commit is" &&
+ mkdir not &&
+ echo very much encouraged but we should >not/forbid &&
+ git add "commit is" not &&
+ echo update added "commit is" file >"commit is" &&
+ echo also update another >not/forbid &&
+ test_tick &&
+ git commit -a -m "initial with -a" &&
+
+ git cat-file blob HEAD:"commit is" >current.1 &&
+ git cat-file blob HEAD:not/forbid >current.2 &&
+
+ cmp current.1 "commit is" &&
+ cmp current.2 not/forbid
+
+'
+
+test_expect_success 'partial' '
+
+ echo another >"commit is" &&
+ echo another >not/forbid &&
+ test_tick &&
+ git commit -m "partial commit to handle a file" "commit is" &&
+
+ changed=$(git diff-tree --name-only HEAD^ HEAD) &&
+ test "$changed" = "commit is"
+
+'
+
+test_expect_success 'partial modification into subdirecotry' '
+
+ test_tick &&
+ git commit -m "partial commit to subdirectory" not &&
+
+ changed=$(git diff-tree -r --name-only HEAD^ HEAD) &&
+ test "$changed" = "not/forbid"
+
+'
+
+test_expect_success 'partial removal' '
+
+ git rm not/forbid &&
+ git commit -m "partial commit to remove not/forbid" not &&
+
+ changed=$(git diff-tree -r --name-only HEAD^ HEAD) &&
+ test "$changed" = "not/forbid" &&
+ remain=$(git ls-tree -r --name-only HEAD) &&
+ test "$remain" = "commit is"
+
+'
+
+test_done
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: committing selected 'changed' or 'added' files works, but not 'removed'
2007-05-14 7:44 ` Junio C Hamano
@ 2007-05-14 12:48 ` Jim Meyering
0 siblings, 0 replies; 3+ messages in thread
From: Jim Meyering @ 2007-05-14 12:48 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
Junio C Hamano <junkio@cox.net> wrote:
> You could do something like this...
...
> -- >8 --
> git-commit: Allow removal to be partially committed as well
>
> We allow partial commit of modified and added files but never
> handled removed files. This hacks it around.
Nice! Thanks for the quick patch.
I liked the test cases :-)
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2007-05-14 12:49 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-05-14 6:16 committing selected 'changed' or 'added' files works, but not 'removed' Jim Meyering
2007-05-14 7:44 ` Junio C Hamano
2007-05-14 12:48 ` Jim Meyering
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox