git/git-commit.sh

245 строки
5.4 KiB
Bash
Исходник Обычный вид История

#!/bin/sh
#
# Copyright (c) 2005 Linus Torvalds
#
. git-sh-setup || die "Not a git archive"
usage () {
die 'git commit [-a] [-v | --no-verify] [-m <message>] [-F <logfile>] [(-C|-c) <commit>] [<path>...]'
}
all= logfile= use_commit= no_edit= log_given= log_message= verify=t signoff=
while case "$#" in 0) break;; esac
do
case "$1" in
-a|--a|--al|--all)
all=t
shift ;;
-F=*|--f=*|--fi=*|--fil=*|--file=*)
log_given=t$log_given
logfile=`expr "$1" : '-[^=]*=\(.*\)'`
no_edit=t
shift ;;
-F|--f|--fi|--fil|--file)
case "$#" in 1) usage ;; esac; shift
log_given=t$log_given
logfile="$1"
no_edit=t
shift ;;
-m=*|--m=*|--me=*|--mes=*|--mess=*|--messa=*|--messag=*|--message=*)
log_given=t$log_given
log_message=`expr "$1" : '-[^=]*=\(.*\)'`
no_edit=t
shift ;;
-m|--m|--me|--mes|--mess|--messa|--messag|--message)
case "$#" in 1) usage ;; esac; shift
log_given=t$log_given
log_message="$1"
no_edit=t
shift ;;
-c=*|--ree=*|--reed=*|--reedi=*|--reedit=*|--reedit-=*|--reedit-m=*|\
--reedit-me=*|--reedit-mes=*|--reedit-mess=*|--reedit-messa=*|\
--reedit-messag=*|--reedit-message=*)
log_given=t$log_given
use_commit=`expr "$1" : '-[^=]*=\(.*\)'`
shift ;;
-c|--ree|--reed|--reedi|--reedit|--reedit-|--reedit-m|--reedit-me|\
--reedit-mes|--reedit-mess|--reedit-messa|--reedit-messag|--reedit-message)
case "$#" in 1) usage ;; esac; shift
log_given=t$log_given
use_commit="$1"
shift ;;
-C=*|--reu=*|--reus=*|--reuse=*|--reuse-=*|--reuse-m=*|--reuse-me=*|\
--reuse-mes=*|--reuse-mess=*|--reuse-messa=*|--reuse-messag=*|\
--reuse-message=*)
log_given=t$log_given
use_commit=`expr "$1" : '-[^=]*=\(.*\)'`
no_edit=t
shift ;;
-C|--reu|--reus|--reuse|--reuse-|--reuse-m|--reuse-me|--reuse-mes|\
--reuse-mess|--reuse-messa|--reuse-messag|--reuse-message)
case "$#" in 1) usage ;; esac; shift
log_given=t$log_given
use_commit="$1"
no_edit=t
shift ;;
-e|--e|--ed|--edi|--edit)
no_edit=
shift ;;
-s|--s|--si|--sig|--sign|--signo|--signof|--signoff)
signoff=t
shift ;;
-n|--n|--no|--no-|--no-v|--no-ve|--no-ver|--no-veri|--no-verif|--no-verify)
verify=
shift ;;
-v|--v|--ve|--ver|--veri|--verif|--verify)
verify=t
shift ;;
--)
shift
break ;;
-*)
usage ;;
*)
break ;;
esac
done
case "$log_given" in
tt*)
die "Only one of -c/-C/-F/-m can be used." ;;
esac
case "$all,$#" in
t,*)
git-diff-files --name-only -z |
git-update-index --remove -z --stdin
;;
,0)
;;
*)
git-diff-files --name-only -z -- "$@" |
git-update-index --remove -z --stdin
;;
esac || exit 1
git-update-index -q --refresh || exit 1
case "$verify" in
t)
if test -x "$GIT_DIR"/hooks/pre-commit
then
"$GIT_DIR"/hooks/pre-commit || exit
fi
esac
if test "$log_message" != ''
then
echo "$log_message"
elif test "$logfile" != ""
then
if test "$logfile" = -
then
test -t 0 &&
echo >&2 "(reading log message from standard input)"
cat
else
cat <"$logfile"
fi
elif test "$use_commit" != ""
then
git-cat-file commit "$use_commit" | sed -e '1,/^$/d'
fi | git-stripspace >"$GIT_DIR"/COMMIT_EDITMSG
case "$signoff" in
t)
{
echo
git-var GIT_COMMITTER_IDENT | sed -e '
s/>.*/>/
s/^/Signed-off-by: /
'
} >>"$GIT_DIR"/COMMIT_EDITMSG
;;
esac
if [ -f "$GIT_DIR/MERGE_HEAD" ]; then
test -f "$GIT_DIR/MERGE_MSG" && cat "$GIT_DIR/MERGE_MSG"
echo "#"
echo "# It looks like your may be committing a MERGE."
echo "# If this is not correct, please remove the file"
echo "# $GIT_DIR/MERGE_HEAD"
echo "# and try again"
echo "#"
fi >>"$GIT_DIR"/COMMIT_EDITMSG
PARENTS="-p HEAD"
if GIT_DIR="$GIT_DIR" git-rev-parse --verify HEAD >/dev/null 2>&1
then
if [ -f "$GIT_DIR/MERGE_HEAD" ]; then
Multi-backend merge driver. The new command 'git merge' takes the current head and one or more remote heads, with the commit log message for the automated case. If the heads being merged are simple fast-forwards, it acts the same way as the current 'git resolve'. Otherwise, it tries different merge strategies and takes the result from the one that succeeded auto-merging, if there is any. If no merge strategy succeeds auto-merging, their results are evaluated for number of paths needed for hand resolving, and the one with the least number of such paths is left in the working tree. The user is asked to resolve them by hand and make a commit manually. The calling convention from the 'git merge' driver to merge strategy programs is very simple: - A strategy program is to be called 'git-merge-<strategy>'. - They take input of this form: <common1> <common2> ... '--' <head> <remote1> <remote2>... That is, one or more the common ancestors, double dash, the current head, and one or more remote heads being merged into the current branch. - Before a strategy program is called, the working tree is matched to the current <head>. - The strategy program exits with status code 0 when it successfully auto-merges the given heads. It should do update-cache for all the merged paths when it does so -- the index file will be used to record the merge result as a commit by the driver. - The strategy program exits with status code 1 when it leaves conflicts behind. It should do update-cache for all the merged paths that it successfully auto-merged, and leave the cache entry in the index file as the same as <head> for paths it could not auto-merge, and leave its best-effort result with conflict markers in the working tree when it does so. - The strategy program exists with status code other than 0 or 1 if it does not handle the given merge at all. As examples, this commit comes with merge strategies based on 'git resolve' and 'git octopus'. Signed-off-by: Junio C Hamano <junkio@cox.net>
2005-09-09 00:47:12 +04:00
PARENTS="-p HEAD "`sed -e 's/^/-p /' "$GIT_DIR/MERGE_HEAD"`
fi
if test "$use_commit" != ""
then
pick_author_script='
/^author /{
h
s/^author \([^<]*\) <[^>]*> .*$/\1/
s/'\''/'\''\'\'\''/g
s/.*/GIT_AUTHOR_NAME='\''&'\''/p
g
s/^author [^<]* <\([^>]*\)> .*$/\1/
s/'\''/'\''\'\'\''/g
s/.*/GIT_AUTHOR_EMAIL='\''&'\''/p
g
s/^author [^<]* <[^>]*> \(.*\)$/\1/
s/'\''/'\''\'\'\''/g
s/.*/GIT_AUTHOR_DATE='\''&'\''/p
q
}
'
set_author_env=`git-cat-file commit "$use_commit" |
sed -ne "$pick_author_script"`
eval "$set_author_env"
export GIT_AUTHOR_NAME
export GIT_AUTHOR_EMAIL
export GIT_AUTHOR_DATE
fi
else
if [ -z "$(git-ls-files)" ]; then
echo Nothing to commit 1>&2
exit 1
fi
PARENTS=""
fi
git-status >>"$GIT_DIR"/COMMIT_EDITMSG
if [ "$?" != "0" -a ! -f "$GIT_DIR/MERGE_HEAD" ]
then
rm -f "$GIT_DIR/COMMIT_EDITMSG"
git-status
exit 1
fi
case "$no_edit" in
'')
${VISUAL:-${EDITOR:-vi}} "$GIT_DIR/COMMIT_EDITMSG"
;;
esac
case "$verify" in
t)
if test -x "$GIT_DIR"/hooks/commit-msg
then
"$GIT_DIR"/hooks/commit-msg "$GIT_DIR"/COMMIT_EDITMSG || exit
fi
esac
grep -v '^#' < "$GIT_DIR"/COMMIT_EDITMSG |
git-stripspace > "$GIT_DIR"/COMMIT_MSG
if cnt=`grep -v -i '^Signed-off-by' "$GIT_DIR"/COMMIT_MSG |
git-stripspace |
wc -l` &&
test 0 -lt $cnt
then
tree=$(git-write-tree) &&
commit=$(cat "$GIT_DIR"/COMMIT_MSG | git-commit-tree $tree $PARENTS) &&
git-update-ref HEAD $commit $current &&
rm -f -- "$GIT_DIR/MERGE_HEAD"
else
echo >&2 "* no commit message? aborting commit."
false
fi
ret="$?"
rm -f "$GIT_DIR/COMMIT_MSG" "$GIT_DIR/COMMIT_EDITMSG"
if test -x "$GIT_DIR"/hooks/post-commit && test "$ret" = 0
then
"$GIT_DIR"/hooks/post-commit
fi
exit "$ret"