git-revert.shon commit Clean up write_in_full() users (d34cf19)
   1#!/bin/sh
   2#
   3# Copyright (c) 2005 Linus Torvalds
   4# Copyright (c) 2005 Junio C Hamano
   5#
   6
   7case "$0" in
   8*-revert* )
   9        test -t 0 && edit=-e
  10        replay=
  11        me=revert
  12        USAGE='[--edit | --no-edit] [-n] <commit-ish>' ;;
  13*-cherry-pick* )
  14        replay=t
  15        edit=
  16        me=cherry-pick
  17        USAGE='[--edit] [-n] [-r] [-x] <commit-ish>'  ;;
  18* )
  19        die "What are you talking about?" ;;
  20esac
  21. git-sh-setup
  22require_work_tree
  23
  24no_commit=
  25while case "$#" in 0) break ;; esac
  26do
  27        case "$1" in
  28        -n|--n|--no|--no-|--no-c|--no-co|--no-com|--no-comm|\
  29            --no-commi|--no-commit)
  30                no_commit=t
  31                ;;
  32        -e|--e|--ed|--edi|--edit)
  33                edit=-e
  34                ;;
  35        --n|--no|--no-|--no-e|--no-ed|--no-edi|--no-edit)
  36                edit=
  37                ;;
  38        -r)
  39                : no-op ;;
  40        -x|--i-really-want-to-expose-my-private-commit-object-name)
  41                replay=
  42                ;;
  43        -*)
  44                usage
  45                ;;
  46        *)
  47                break
  48                ;;
  49        esac
  50        shift
  51done
  52
  53test "$me,$replay" = "revert,t" && usage
  54
  55case "$no_commit" in
  56t)
  57        # We do not intend to commit immediately.  We just want to
  58        # merge the differences in.
  59        head=$(git-write-tree) ||
  60                die "Your index file is unmerged."
  61        ;;
  62*)
  63        head=$(git-rev-parse --verify HEAD) ||
  64                die "You do not have a valid HEAD"
  65        files=$(git-diff-index --cached --name-only $head) || exit
  66        if [ "$files" ]; then
  67                die "Dirty index: cannot $me (dirty: $files)"
  68        fi
  69        ;;
  70esac
  71
  72rev=$(git-rev-parse --verify "$@") &&
  73commit=$(git-rev-parse --verify "$rev^0") ||
  74        die "Not a single commit $@"
  75prev=$(git-rev-parse --verify "$commit^1" 2>/dev/null) ||
  76        die "Cannot run $me a root commit"
  77git-rev-parse --verify "$commit^2" >/dev/null 2>&1 &&
  78        die "Cannot run $me a multi-parent commit."
  79
  80# "commit" is an existing commit.  We would want to apply
  81# the difference it introduces since its first parent "prev"
  82# on top of the current HEAD if we are cherry-pick.  Or the
  83# reverse of it if we are revert.
  84
  85case "$me" in
  86revert)
  87        git-rev-list --pretty=oneline --max-count=1 $commit |
  88        sed -e '
  89                s/^[^ ]* /Revert "/
  90                s/$/"/'
  91        echo
  92        echo "This reverts commit $commit."
  93        test "$rev" = "$commit" ||
  94        echo "(original 'git revert' arguments: $@)"
  95        base=$commit next=$prev
  96        ;;
  97
  98cherry-pick)
  99        pick_author_script='
 100        /^author /{
 101                s/'\''/'\''\\'\'\''/g
 102                h
 103                s/^author \([^<]*\) <[^>]*> .*$/\1/
 104                s/'\''/'\''\'\'\''/g
 105                s/.*/GIT_AUTHOR_NAME='\''&'\''/p
 106
 107                g
 108                s/^author [^<]* <\([^>]*\)> .*$/\1/
 109                s/'\''/'\''\'\'\''/g
 110                s/.*/GIT_AUTHOR_EMAIL='\''&'\''/p
 111
 112                g
 113                s/^author [^<]* <[^>]*> \(.*\)$/\1/
 114                s/'\''/'\''\'\'\''/g
 115                s/.*/GIT_AUTHOR_DATE='\''&'\''/p
 116
 117                q
 118        }'
 119        set_author_env=`git-cat-file commit "$commit" |
 120        LANG=C LC_ALL=C sed -ne "$pick_author_script"`
 121        eval "$set_author_env"
 122        export GIT_AUTHOR_NAME
 123        export GIT_AUTHOR_EMAIL
 124        export GIT_AUTHOR_DATE
 125
 126        git-cat-file commit $commit | sed -e '1,/^$/d'
 127        case "$replay" in
 128        '')
 129                echo "(cherry picked from commit $commit)"
 130                test "$rev" = "$commit" ||
 131                echo "(original 'git cherry-pick' arguments: $@)"
 132                ;;
 133        esac
 134        base=$prev next=$commit
 135        ;;
 136
 137esac >.msg
 138
 139# This three way merge is an interesting one.  We are at
 140# $head, and would want to apply the change between $commit
 141# and $prev on top of us (when reverting), or the change between
 142# $prev and $commit on top of us (when cherry-picking or replaying).
 143
 144echo >&2 "First trying simple merge strategy to $me."
 145git-read-tree -m -u --aggressive $base $head $next &&
 146result=$(git-write-tree 2>/dev/null) || {
 147    echo >&2 "Simple $me fails; trying Automatic $me."
 148    git-merge-index -o git-merge-one-file -a || {
 149            mv -f .msg "$GIT_DIR/MERGE_MSG"
 150            {
 151                echo '
 152Conflicts:
 153'
 154                git ls-files --unmerged |
 155                sed -e 's/^[^   ]*      /       /' |
 156                uniq
 157            } >>"$GIT_DIR/MERGE_MSG"
 158            echo >&2 "Automatic $me failed.  After resolving the conflicts,"
 159            echo >&2 "mark the corrected paths with 'git-add <paths>'"
 160            echo >&2 "and commit the result."
 161            case "$me" in
 162            cherry-pick)
 163                echo >&2 "You may choose to use the following when making"
 164                echo >&2 "the commit:"
 165                echo >&2 "$set_author_env"
 166            esac
 167            exit 1
 168    }
 169    result=$(git-write-tree) || exit
 170}
 171echo >&2 "Finished one $me."
 172
 173# If we are cherry-pick, and if the merge did not result in
 174# hand-editing, we will hit this commit and inherit the original
 175# author date and name.
 176# If we are revert, or if our cherry-pick results in a hand merge,
 177# we had better say that the current user is responsible for that.
 178
 179case "$no_commit" in
 180'')
 181        git-commit -n -F .msg $edit
 182        rm -f .msg
 183        ;;
 184esac