git-commit: finishing touches.

Introduce --only flag to allow the new "partial commit"
semantics when paths are specified.  The default is still the
traditional --include semantics.  Once peoples' fingers and
scripts that want the traditional behaviour are updated to
explicitly say --include, we could change it to either default
to --only, or refuse to operate without either --only/--include
when paths are specified.

This also fixes a couple of bugs in the previous round.  Namely:

 - forgot to save/restore index in some cases.

 - forgot to use the temporary index to show status when '--only
   paths...' semantics was used.

 - --author did not take precedence when reusing an existing
   commit.

Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
Junio C Hamano 2006-02-05 16:08:01 -08:00
parent 130fcca63f
commit 5a798fb57f

View File

@ -13,13 +13,30 @@ initial_commit=t
refuse_partial () { refuse_partial () {
echo >&2 "$1" echo >&2 "$1"
echo >&2 "Experienced git users:"
echo >&2 "You might have meant to say 'git commit -i paths...', perhaps?" echo >&2 "You might have meant to say 'git commit -i paths...', perhaps?"
exit 1 exit 1
} }
SAVE_INDEX="$GIT_DIR/save-index$$"
save_index () {
cp "$GIT_DIR/index" "$SAVE_INDEX"
}
run_status () {
(
cd "$TOP"
if test '' != "$TMP_INDEX"
then
GIT_INDEX_FILE="$TMP_INDEX" git-status
else
git-status
fi
)
}
all= all=
also= also=
only=
logfile= logfile=
use_commit= use_commit=
no_edit= no_edit=
@ -73,6 +90,10 @@ do
also=t also=t
shift shift
;; ;;
-o|--o|--on|--onl|--only)
only=t
shift
;;
-m|--m|--me|--mes|--mess|--messa|--messag|--message) -m|--m|--me|--mes|--mess|--messa|--messag|--message)
case "$#" in 1) usage ;; esac case "$#" in 1) usage ;; esac
shift shift
@ -153,7 +174,7 @@ do
;; ;;
-v|--v|--ve|--ver|--veri|--verif|--verify) -v|--v|--ve|--ver|--veri|--verif|--verify)
verify=t verify=t
shift shift
;; ;;
--) --)
shift shift
@ -173,19 +194,41 @@ tt*)
die "Only one of -c/-C/-F/-m can be used." ;; die "Only one of -c/-C/-F/-m can be used." ;;
esac esac
case "$#,$also$only" in
*,tt)
die "Only one of --include/--only can be used." ;;
0,t)
die "No paths with --include/--only does not make sense." ;;
0,)
;;
*,)
echo >&2 "assuming --include paths..."
also=t
# Later when switch the defaults, we will replace them with these:
# echo >&2 "assuming --only paths..."
# also=
;;
esac
unset only
TOP=`git-rev-parse --show-cdup` TOP=`git-rev-parse --show-cdup`
if test -z "$TOP"
then
TOP=./
fi
case "$all,$also" in case "$all,$also" in
t,t) t,t)
die "Cannot use -a and -i at the same time." ;; die "Cannot use -a and -i at the same time." ;;
t,) t,)
SAVE_INDEX="$GIT_DIR/save-index$$" && case "$#" in
cp "$GIT_DIR/index" "$SAVE_INDEX" && 0) ;;
*) die "Paths with -a does not make sense." ;;
esac
save_index &&
( (
if test '' != "$TOP" cd "$TOP"
then
cd "$TOP"
fi &&
git-diff-files --name-only -z | git-diff-files --name-only -z |
git-update-index --remove -z --stdin git-update-index --remove -z --stdin
) )
@ -194,10 +237,10 @@ t,)
case "$#" in case "$#" in
0) die "No paths with -i does not make sense." ;; 0) die "No paths with -i does not make sense." ;;
esac esac
SAVE_INDEX="$GIT_DIR/save-index$$" &&
cp "$GIT_DIR/index" "$SAVE_INDEX" && save_index &&
git-diff-files --name-only -z -- "$@" | git-diff-files --name-only -z -- "$@" |
git-update-index --remove -z --stdin (cd "$TOP" && git-update-index --remove -z --stdin)
;; ;;
,) ,)
case "$#" in case "$#" in
@ -214,10 +257,9 @@ t,)
# make sure index is clean at the specified paths, or # make sure index is clean at the specified paths, or
# they are additions. # they are additions.
dirty_in_index=`git-diff-index --cached --name-status \ dirty_in_index=`git-diff-index --cached --name-status \
--diff-filter=DMTXU HEAD -- "$@"` --diff-filter=DMTU HEAD -- "$@"`
test -z "$dirty_in_index" || test -z "$dirty_in_index" ||
refuse_partial "Cannot do a partial commit of paths dirty in index: refuse_partial "Different in index and the last commit:
$dirty_in_index" $dirty_in_index"
fi fi
commit_only=`git-ls-files -- "$@"` ;; commit_only=`git-ls-files -- "$@"` ;;
@ -228,7 +270,9 @@ esac
git-update-index -q --refresh || exit 1 git-update-index -q --refresh || exit 1
trap ' trap '
test -f "$TMP_INDEX" && rm -f "$TMP_INDEX" test -z "$TMP_INDEX" || {
test -f "$TMP_INDEX" && rm -f "$TMP_INDEX"
}
test -f "$SAVE_INDEX" && mv -f "$SAVE_INDEX" "$GIT_DIR/index" test -f "$SAVE_INDEX" && mv -f "$SAVE_INDEX" "$GIT_DIR/index"
' 0 ' 0
@ -242,12 +286,10 @@ then
fi || exit fi || exit
echo "$commit_only" | echo "$commit_only" |
GIT_INDEX_FILE="$TMP_INDEX" git-update-index --add --remove --stdin && GIT_INDEX_FILE="$TMP_INDEX" git-update-index --add --remove --stdin &&
save_index &&
echo "$commit_only" | echo "$commit_only" |
git-update-index --remove --stdin || git-update-index --remove --stdin ||
exit exit
else
#
:
fi fi
if test t = "$verify" && test -x "$GIT_DIR"/hooks/pre-commit if test t = "$verify" && test -x "$GIT_DIR"/hooks/pre-commit
@ -303,7 +345,15 @@ if [ -f "$GIT_DIR/MERGE_HEAD" ]; then
fi >>"$GIT_DIR"/COMMIT_EDITMSG fi >>"$GIT_DIR"/COMMIT_EDITMSG
# Author # Author
if test '' != "$use_commit" if test '' != "$force_author"
then
GIT_AUTHOR_NAME=`expr "$force_author" : '\(.*[^ ]\) *<.*'` &&
GIT_AUTHOR_EMAIL=`expr "$force_author" : '.*\(<.*\)'` &&
test '' != "$GIT_AUTHOR_NAME" &&
test '' != "$GIT_AUTHOR_EMAIL" ||
die "malformatted --author parameter"
export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL
elif test '' != "$use_commit"
then then
pick_author_script=' pick_author_script='
/^author /{ /^author /{
@ -332,14 +382,6 @@ then
export GIT_AUTHOR_NAME export GIT_AUTHOR_NAME
export GIT_AUTHOR_EMAIL export GIT_AUTHOR_EMAIL
export GIT_AUTHOR_DATE export GIT_AUTHOR_DATE
elif test '' != "$force_author"
then
GIT_AUTHOR_NAME=`expr "$force_author" : '\(.*[^ ]\) *<.*'` &&
GIT_AUTHOR_EMAIL=`expr "$force_author" : '.*\(<.*\)'` &&
test '' != "$GIT_AUTHOR_NAME" &&
test '' != "$GIT_AUTHOR_EMAIL" ||
die "malformatted --author parameter"
export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL
fi fi
PARENTS="-p HEAD" PARENTS="-p HEAD"
@ -350,27 +392,18 @@ then
fi fi
else else
if [ -z "$(git-ls-files)" ]; then if [ -z "$(git-ls-files)" ]; then
echo Nothing to commit 1>&2 echo >&2 Nothing to commit
exit 1 exit 1
fi fi
PARENTS="" PARENTS=""
fi fi
(
if test '' != "$TOP" run_status >>"$GIT_DIR"/COMMIT_EDITMSG
then
cd "$TOP"
fi &&
git-status >>"$GIT_DIR"/COMMIT_EDITMSG
)
if [ "$?" != "0" -a ! -f "$GIT_DIR/MERGE_HEAD" ] if [ "$?" != "0" -a ! -f "$GIT_DIR/MERGE_HEAD" ]
then then
rm -f "$GIT_DIR/COMMIT_EDITMSG" rm -f "$GIT_DIR/COMMIT_EDITMSG"
if test '' != "$TOP" run_status
then
cd "$TOP"
fi &&
git-status
exit 1 exit 1
fi fi
case "$no_edit" in case "$no_edit" in