3 # Copyright (c) 2005 Linus Torvalds
 
   4 # Copyright (c) 2005 Junio C Hamano
 
  12         USAGE='[--edit | --no-edit] [-n] <commit-ish>' ;;
 
  17         USAGE='[--edit] [-n] [-r] [-x] <commit-ish>'  ;;
 
  19         echo >&2 "What are you talking about?"
 
  23 SUBDIRECTORY_OK=Yes ;# we will cd up
 
  30 while case "$#" in 0) break ;; esac
 
  33         -n|--n|--no|--no-|--no-c|--no-co|--no-com|--no-comm|\
 
  34             --no-commi|--no-commit)
 
  37         -e|--e|--ed|--edi|--edit)
 
  40         --n|--no|--no-|--no-e|--no-ed|--no-edi|--no-edit)
 
  45         -x|--i-really-want-to-expose-my-private-commit-object-name)
 
  49                 xopt="$xopt$(git rev-parse --sq-quote "--${1#-X}")"
 
  52                 xopt="$xopt$(git rev-parse --sq-quote "--${1#--strategy-option=}")"
 
  56                 xopt="$xopt$(git rev-parse --sq-quote "--$1")"
 
  68 set_reflog_action "$me"
 
  70 test "$me,$replay" = "revert,t" && usage
 
  74         # We do not intend to commit immediately.  We just want to
 
  75         # merge the differences in.
 
  76         head=$(git-write-tree) ||
 
  77                 die "Your index file is unmerged."
 
  80         head=$(git-rev-parse --verify HEAD) ||
 
  81                 die "You do not have a valid HEAD"
 
  82         files=$(git-diff-index --cached --name-only $head) || exit
 
  84                 die "Dirty index: cannot $me (dirty: $files)"
 
  89 rev=$(git-rev-parse --verify "$@") &&
 
  90 commit=$(git-rev-parse --verify "$rev^0") ||
 
  91         die "Not a single commit $@"
 
  92 prev=$(git-rev-parse --verify "$commit^1" 2>/dev/null) ||
 
  93         die "Cannot run $me a root commit"
 
  94 git-rev-parse --verify "$commit^2" >/dev/null 2>&1 &&
 
  95         die "Cannot run $me a multi-parent commit."
 
  97 encoding=$(git config i18n.commitencoding || echo UTF-8)
 
  99 # "commit" is an existing commit.  We would want to apply
 
 100 # the difference it introduces since its first parent "prev"
 
 101 # on top of the current HEAD if we are cherry-pick.  Or the
 
 102 # reverse of it if we are revert.
 
 106         git show -s --pretty=oneline --encoding="$encoding" $commit |
 
 112         echo "This reverts commit $commit."
 
 113         test "$rev" = "$commit" ||
 
 114         echo "(original 'git revert' arguments: $@)"
 
 115         base=$commit next=$prev
 
 121                 s/'\''/'\''\\'\'\''/g
 
 123                 s/^author \([^<]*\) <[^>]*> .*$/\1/
 
 125                 s/.*/GIT_AUTHOR_NAME='\''&'\''/p
 
 128                 s/^author [^<]* <\([^>]*\)> .*$/\1/
 
 130                 s/.*/GIT_AUTHOR_EMAIL='\''&'\''/p
 
 133                 s/^author [^<]* <[^>]*> \(.*\)$/\1/
 
 135                 s/.*/GIT_AUTHOR_DATE='\''&'\''/p
 
 140         logmsg=`git show -s --pretty=raw --encoding="$encoding" "$commit"`
 
 141         set_author_env=`echo "$logmsg" |
 
 142         LANG=C LC_ALL=C sed -ne "$pick_author_script"`
 
 143         eval "$set_author_env"
 
 144         export GIT_AUTHOR_NAME
 
 145         export GIT_AUTHOR_EMAIL
 
 146         export GIT_AUTHOR_DATE
 
 149         sed -e '1,/^$/d' -e 's/^    //'
 
 152                 echo "(cherry picked from commit $commit)"
 
 153                 test "$rev" = "$commit" ||
 
 154                 echo "(original 'git cherry-pick' arguments: $@)"
 
 157         base=$prev next=$commit
 
 162 eval GITHEAD_$head=HEAD
 
 163 eval GITHEAD_$next='`git show -s \
 
 164         --pretty=oneline --encoding="$encoding" "$commit" |
 
 165         sed -e "s/^[^ ]* //"`'
 
 166 export GITHEAD_$head GITHEAD_$next
 
 168 # This three way merge is an interesting one.  We are at
 
 169 # $head, and would want to apply the change between $commit
 
 170 # and $prev on top of us (when reverting), or the change between
 
 171 # $prev and $commit on top of us (when cherry-picking or replaying).
 
 173 eval "git merge-recursive $xopt $base -- $head $next" &&
 
 174 result=$(git-write-tree 2>/dev/null) || {
 
 175         mv -f .msg "$GIT_DIR/MERGE_MSG"
 
 180                 git ls-files --unmerged |
 
 181                 sed -e 's/^[^   ]*      /       /' |
 
 183         } >>"$GIT_DIR/MERGE_MSG"
 
 184         echo >&2 "Automatic $me failed.  After resolving the conflicts,"
 
 185         echo >&2 "mark the corrected paths with 'git-add <paths>'"
 
 186         echo >&2 "and commit the result."
 
 189                 echo >&2 "You may choose to use the following when making"
 
 190                 echo >&2 "the commit:"
 
 191                 echo >&2 "$set_author_env"
 
 196 # If we are cherry-pick, and if the merge did not result in
 
 197 # hand-editing, we will hit this commit and inherit the original
 
 198 # author date and name.
 
 199 # If we are revert, or if our cherry-pick results in a hand merge,
 
 200 # we had better say that the current user is responsible for that.
 
 204         git-commit -n -F .msg $edit