git-commit.shon commit Merge branch 'jc/add' (520635f)
   1#!/bin/sh
   2#
   3# Copyright (c) 2005 Linus Torvalds
   4# Copyright (c) 2006 Junio C Hamano
   5
   6USAGE='[-a | --interactive] [-s] [-v] [--no-verify] [-m <message> | -F <logfile> | (-C|-c) <commit> | --amend] [-u] [-e] [--author <author>] [[-i | -o] <path>...]'
   7SUBDIRECTORY_OK=Yes
   8. git-sh-setup
   9require_work_tree
  10
  11git-rev-parse --verify HEAD >/dev/null 2>&1 || initial_commit=t
  12
  13case "$0" in
  14*status)
  15        status_only=t
  16        ;;
  17*commit)
  18        status_only=
  19        ;;
  20esac
  21
  22refuse_partial () {
  23        echo >&2 "$1"
  24        echo >&2 "You might have meant to say 'git commit -i paths...', perhaps?"
  25        exit 1
  26}
  27
  28THIS_INDEX="$GIT_DIR/index"
  29NEXT_INDEX="$GIT_DIR/next-index$$"
  30rm -f "$NEXT_INDEX"
  31save_index () {
  32        cp -p "$THIS_INDEX" "$NEXT_INDEX"
  33}
  34
  35run_status () {
  36        # If TMP_INDEX is defined, that means we are doing
  37        # "--only" partial commit, and that index file is used
  38        # to build the tree for the commit.  Otherwise, if
  39        # NEXT_INDEX exists, that is the index file used to
  40        # make the commit.  Otherwise we are using as-is commit
  41        # so the regular index file is what we use to compare.
  42        if test '' != "$TMP_INDEX"
  43        then
  44                GIT_INDEX_FILE="$TMP_INDEX"
  45                export GIT_INDEX_FILE
  46        elif test -f "$NEXT_INDEX"
  47        then
  48                GIT_INDEX_FILE="$NEXT_INDEX"
  49                export GIT_INDEX_FILE
  50        fi
  51
  52        case "$status_only" in
  53        t) color= ;;
  54        *) color=--nocolor ;;
  55        esac
  56        git-runstatus ${color} \
  57                ${verbose:+--verbose} \
  58                ${amend:+--amend} \
  59                ${untracked_files:+--untracked}
  60}
  61
  62trap '
  63        test -z "$TMP_INDEX" || {
  64                test -f "$TMP_INDEX" && rm -f "$TMP_INDEX"
  65        }
  66        rm -f "$NEXT_INDEX"
  67' 0
  68
  69################################################################
  70# Command line argument parsing and sanity checking
  71
  72all=
  73also=
  74interactive=
  75only=
  76logfile=
  77use_commit=
  78amend=
  79edit_flag=
  80no_edit=
  81log_given=
  82log_message=
  83verify=t
  84quiet=
  85verbose=
  86signoff=
  87force_author=
  88only_include_assumed=
  89untracked_files=
  90while case "$#" in 0) break;; esac
  91do
  92        case "$1" in
  93        -F|--F|-f|--f|--fi|--fil|--file)
  94                case "$#" in 1) usage ;; esac
  95                shift
  96                no_edit=t
  97                log_given=t$log_given
  98                logfile="$1"
  99                shift
 100                ;;
 101        -F*|-f*)
 102                no_edit=t
 103                log_given=t$log_given
 104                logfile=`expr "z$1" : 'z-[Ff]\(.*\)'`
 105                shift
 106                ;;
 107        --F=*|--f=*|--fi=*|--fil=*|--file=*)
 108                no_edit=t
 109                log_given=t$log_given
 110                logfile=`expr "z$1" : 'z-[^=]*=\(.*\)'`
 111                shift
 112                ;;
 113        -a|--a|--al|--all)
 114                all=t
 115                shift
 116                ;;
 117        --au=*|--aut=*|--auth=*|--autho=*|--author=*)
 118                force_author=`expr "z$1" : 'z-[^=]*=\(.*\)'`
 119                shift
 120                ;;
 121        --au|--aut|--auth|--autho|--author)
 122                case "$#" in 1) usage ;; esac
 123                shift
 124                force_author="$1"
 125                shift
 126                ;;
 127        -e|--e|--ed|--edi|--edit)
 128                edit_flag=t
 129                shift
 130                ;;
 131        -i|--i|--in|--inc|--incl|--inclu|--includ|--include)
 132                also=t
 133                shift
 134                ;;
 135        --int|--inte|--inter|--intera|--interac|--interact|--interacti|\
 136        --interactiv|--interactive)
 137                interactive=t
 138                shift
 139                ;;
 140        -o|--o|--on|--onl|--only)
 141                only=t
 142                shift
 143                ;;
 144        -m|--m|--me|--mes|--mess|--messa|--messag|--message)
 145                case "$#" in 1) usage ;; esac
 146                shift
 147                log_given=m$log_given
 148                if test "$log_message" = ''
 149                then
 150                    log_message="$1"
 151                else
 152                    log_message="$log_message
 153
 154$1"
 155                fi
 156                no_edit=t
 157                shift
 158                ;;
 159        -m*)
 160                log_given=m$log_given
 161                if test "$log_message" = ''
 162                then
 163                    log_message=`expr "z$1" : 'z-m\(.*\)'`
 164                else
 165                    log_message="$log_message
 166
 167`expr "z$1" : 'z-m\(.*\)'`"
 168                fi
 169                no_edit=t
 170                shift
 171                ;;
 172        --m=*|--me=*|--mes=*|--mess=*|--messa=*|--messag=*|--message=*)
 173                log_given=m$log_given
 174                if test "$log_message" = ''
 175                then
 176                    log_message=`expr "z$1" : 'z-[^=]*=\(.*\)'`
 177                else
 178                    log_message="$log_message
 179
 180`expr "z$1" : 'zq-[^=]*=\(.*\)'`"
 181                fi
 182                no_edit=t
 183                shift
 184                ;;
 185        -n|--n|--no|--no-|--no-v|--no-ve|--no-ver|--no-veri|--no-verif|\
 186        --no-verify)
 187                verify=
 188                shift
 189                ;;
 190        --a|--am|--ame|--amen|--amend)
 191                amend=t
 192                log_given=t$log_given
 193                use_commit=HEAD
 194                shift
 195                ;;
 196        -c)
 197                case "$#" in 1) usage ;; esac
 198                shift
 199                log_given=t$log_given
 200                use_commit="$1"
 201                no_edit=
 202                shift
 203                ;;
 204        --ree=*|--reed=*|--reedi=*|--reedit=*|--reedit-=*|--reedit-m=*|\
 205        --reedit-me=*|--reedit-mes=*|--reedit-mess=*|--reedit-messa=*|\
 206        --reedit-messag=*|--reedit-message=*)
 207                log_given=t$log_given
 208                use_commit=`expr "z$1" : 'z-[^=]*=\(.*\)'`
 209                no_edit=
 210                shift
 211                ;;
 212        --ree|--reed|--reedi|--reedit|--reedit-|--reedit-m|--reedit-me|\
 213        --reedit-mes|--reedit-mess|--reedit-messa|--reedit-messag|\
 214        --reedit-message)
 215                case "$#" in 1) usage ;; esac
 216                shift
 217                log_given=t$log_given
 218                use_commit="$1"
 219                no_edit=
 220                shift
 221                ;;
 222        -C)
 223                case "$#" in 1) usage ;; esac
 224                shift
 225                log_given=t$log_given
 226                use_commit="$1"
 227                no_edit=t
 228                shift
 229                ;;
 230        --reu=*|--reus=*|--reuse=*|--reuse-=*|--reuse-m=*|--reuse-me=*|\
 231        --reuse-mes=*|--reuse-mess=*|--reuse-messa=*|--reuse-messag=*|\
 232        --reuse-message=*)
 233                log_given=t$log_given
 234                use_commit=`expr "z$1" : 'z-[^=]*=\(.*\)'`
 235                no_edit=t
 236                shift
 237                ;;
 238        --reu|--reus|--reuse|--reuse-|--reuse-m|--reuse-me|--reuse-mes|\
 239        --reuse-mess|--reuse-messa|--reuse-messag|--reuse-message)
 240                case "$#" in 1) usage ;; esac
 241                shift
 242                log_given=t$log_given
 243                use_commit="$1"
 244                no_edit=t
 245                shift
 246                ;;
 247        -s|--s|--si|--sig|--sign|--signo|--signof|--signoff)
 248                signoff=t
 249                shift
 250                ;;
 251        -q|--q|--qu|--qui|--quie|--quiet)
 252                quiet=t
 253                shift
 254                ;;
 255        -v|--v|--ve|--ver|--verb|--verbo|--verbos|--verbose)
 256                verbose=t
 257                shift
 258                ;;
 259        -u|--u|--un|--unt|--untr|--untra|--untrac|--untrack|--untracke|\
 260        --untracked|--untracked-|--untracked-f|--untracked-fi|--untracked-fil|\
 261        --untracked-file|--untracked-files)
 262                untracked_files=t
 263                shift
 264                ;;
 265        --)
 266                shift
 267                break
 268                ;;
 269        -*)
 270                usage
 271                ;;
 272        *)
 273                break
 274                ;;
 275        esac
 276done
 277case "$edit_flag" in t) no_edit= ;; esac
 278
 279################################################################
 280# Sanity check options
 281
 282case "$amend,$initial_commit" in
 283t,t)
 284        die "You do not have anything to amend." ;;
 285t,)
 286        if [ -f "$GIT_DIR/MERGE_HEAD" ]; then
 287                die "You are in the middle of a merge -- cannot amend."
 288        fi ;;
 289esac
 290
 291case "$log_given" in
 292tt*)
 293        die "Only one of -c/-C/-F/--amend can be used." ;;
 294*tm*|*mt*)
 295        die "Option -m cannot be combined with -c/-C/-F/--amend." ;;
 296esac
 297
 298case "$#,$also,$only,$amend" in
 299*,t,t,*)
 300        die "Only one of --include/--only can be used." ;;
 3010,t,,* | 0,,t,)
 302        die "No paths with --include/--only does not make sense." ;;
 3030,,t,t)
 304        only_include_assumed="# Clever... amending the last one with dirty index." ;;
 3050,,,*)
 306        ;;
 307*,,,*)
 308        only_include_assumed="# Explicit paths specified without -i nor -o; assuming --only paths..."
 309        also=
 310        ;;
 311esac
 312unset only
 313case "$all,$interactive,$also,$#" in
 314*t,*t,*)
 315        die "Cannot use -a, --interactive or -i at the same time." ;;
 316t,,[1-9]*)
 317        die "Paths with -a does not make sense." ;;
 318,t,[1-9]*)
 319        die "Paths with --interactive does not make sense." ;;
 320,,t,0)
 321        die "No paths with -i does not make sense." ;;
 322esac
 323
 324################################################################
 325# Prepare index to have a tree to be committed
 326
 327case "$all,$also" in
 328t,)
 329        if test ! -f "$THIS_INDEX"
 330        then
 331                die 'nothing to commit (use "git add file1 file2" to include for commit)'
 332        fi
 333        save_index &&
 334        (
 335                cd_to_toplevel &&
 336                GIT_INDEX_FILE="$NEXT_INDEX" &&
 337                export GIT_INDEX_FILE &&
 338                git-diff-files --name-only -z |
 339                git-update-index --remove -z --stdin
 340        ) || exit
 341        ;;
 342,t)
 343        save_index &&
 344        git-ls-files --error-unmatch -- "$@" >/dev/null || exit
 345
 346        git-diff-files --name-only -z -- "$@"  |
 347        (
 348                cd_to_toplevel &&
 349                GIT_INDEX_FILE="$NEXT_INDEX" &&
 350                export GIT_INDEX_FILE &&
 351                git-update-index --remove -z --stdin
 352        ) || exit
 353        ;;
 354,)
 355        if test "$interactive" = t; then
 356                git add --interactive || exit
 357        fi
 358        case "$#" in
 359        0)
 360                ;; # commit as-is
 361        *)
 362                if test -f "$GIT_DIR/MERGE_HEAD"
 363                then
 364                        refuse_partial "Cannot do a partial commit during a merge."
 365                fi
 366                TMP_INDEX="$GIT_DIR/tmp-index$$"
 367                commit_only=`git-ls-files --error-unmatch -- "$@"` || exit
 368
 369                # Build a temporary index and update the real index
 370                # the same way.
 371                if test -z "$initial_commit"
 372                then
 373                        GIT_INDEX_FILE="$THIS_INDEX" \
 374                        git-read-tree --index-output="$TMP_INDEX" -i -m HEAD
 375                else
 376                        rm -f "$TMP_INDEX"
 377                fi || exit
 378
 379                echo "$commit_only" |
 380                GIT_INDEX_FILE="$TMP_INDEX" \
 381                git-update-index --add --remove --stdin &&
 382
 383                save_index &&
 384                echo "$commit_only" |
 385                (
 386                        GIT_INDEX_FILE="$NEXT_INDEX"
 387                        export GIT_INDEX_FILE
 388                        git-update-index --remove --stdin
 389                ) || exit
 390                ;;
 391        esac
 392        ;;
 393esac
 394
 395################################################################
 396# If we do as-is commit, the index file will be THIS_INDEX,
 397# otherwise NEXT_INDEX after we make this commit.  We leave
 398# the index as is if we abort.
 399
 400if test -f "$NEXT_INDEX"
 401then
 402        USE_INDEX="$NEXT_INDEX"
 403else
 404        USE_INDEX="$THIS_INDEX"
 405fi
 406
 407case "$status_only" in
 408t)
 409        # This will silently fail in a read-only repository, which is
 410        # what we want.
 411        GIT_INDEX_FILE="$USE_INDEX" git-update-index -q --unmerged --refresh
 412        run_status
 413        exit $?
 414        ;;
 415'')
 416        GIT_INDEX_FILE="$USE_INDEX" git-update-index -q --refresh || exit
 417        ;;
 418esac
 419
 420################################################################
 421# Grab commit message, write out tree and make commit.
 422
 423if test t = "$verify" && test -x "$GIT_DIR"/hooks/pre-commit
 424then
 425        if test "$TMP_INDEX"
 426        then
 427                GIT_INDEX_FILE="$TMP_INDEX" "$GIT_DIR"/hooks/pre-commit
 428        else
 429                GIT_INDEX_FILE="$USE_INDEX" "$GIT_DIR"/hooks/pre-commit
 430        fi || exit
 431fi
 432
 433if test "$log_message" != ''
 434then
 435        echo "$log_message"
 436elif test "$logfile" != ""
 437then
 438        if test "$logfile" = -
 439        then
 440                test -t 0 &&
 441                echo >&2 "(reading log message from standard input)"
 442                cat
 443        else
 444                cat <"$logfile"
 445        fi
 446elif test "$use_commit" != ""
 447then
 448        encoding=$(git config i18n.commitencoding || echo UTF-8)
 449        git show -s --pretty=raw --encoding="$encoding" "$use_commit" |
 450        sed -e '1,/^$/d' -e 's/^    //'
 451elif test -f "$GIT_DIR/MERGE_MSG"
 452then
 453        cat "$GIT_DIR/MERGE_MSG"
 454elif test -f "$GIT_DIR/SQUASH_MSG"
 455then
 456        cat "$GIT_DIR/SQUASH_MSG"
 457fi | git-stripspace >"$GIT_DIR"/COMMIT_EDITMSG
 458
 459case "$signoff" in
 460t)
 461        need_blank_before_signoff=
 462        tail -n 1 "$GIT_DIR"/COMMIT_EDITMSG |
 463        grep 'Signed-off-by:' >/dev/null || need_blank_before_signoff=yes
 464        {
 465                test -z "$need_blank_before_signoff" || echo
 466                git-var GIT_COMMITTER_IDENT | sed -e '
 467                        s/>.*/>/
 468                        s/^/Signed-off-by: /
 469                '
 470        } >>"$GIT_DIR"/COMMIT_EDITMSG
 471        ;;
 472esac
 473
 474if test -f "$GIT_DIR/MERGE_HEAD" && test -z "$no_edit"; then
 475        echo "#"
 476        echo "# It looks like you may be committing a MERGE."
 477        echo "# If this is not correct, please remove the file"
 478        echo "# $GIT_DIR/MERGE_HEAD"
 479        echo "# and try again"
 480        echo "#"
 481fi >>"$GIT_DIR"/COMMIT_EDITMSG
 482
 483# Author
 484if test '' != "$use_commit"
 485then
 486        pick_author_script='
 487        /^author /{
 488                s/'\''/'\''\\'\'\''/g
 489                h
 490                s/^author \([^<]*\) <[^>]*> .*$/\1/
 491                s/'\''/'\''\'\'\''/g
 492                s/.*/GIT_AUTHOR_NAME='\''&'\''/p
 493
 494                g
 495                s/^author [^<]* <\([^>]*\)> .*$/\1/
 496                s/'\''/'\''\'\'\''/g
 497                s/.*/GIT_AUTHOR_EMAIL='\''&'\''/p
 498
 499                g
 500                s/^author [^<]* <[^>]*> \(.*\)$/\1/
 501                s/'\''/'\''\'\'\''/g
 502                s/.*/GIT_AUTHOR_DATE='\''&'\''/p
 503
 504                q
 505        }
 506        '
 507        encoding=$(git config i18n.commitencoding || echo UTF-8)
 508        set_author_env=`git show -s --pretty=raw --encoding="$encoding" "$use_commit" |
 509        LANG=C LC_ALL=C sed -ne "$pick_author_script"`
 510        eval "$set_author_env"
 511        export GIT_AUTHOR_NAME
 512        export GIT_AUTHOR_EMAIL
 513        export GIT_AUTHOR_DATE
 514fi
 515if test '' != "$force_author"
 516then
 517        GIT_AUTHOR_NAME=`expr "z$force_author" : 'z\(.*[^ ]\) *<.*'` &&
 518        GIT_AUTHOR_EMAIL=`expr "z$force_author" : '.*\(<.*\)'` &&
 519        test '' != "$GIT_AUTHOR_NAME" &&
 520        test '' != "$GIT_AUTHOR_EMAIL" ||
 521        die "malformed --author parameter"
 522        export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL
 523fi
 524
 525PARENTS="-p HEAD"
 526if test -z "$initial_commit"
 527then
 528        rloga='commit'
 529        if [ -f "$GIT_DIR/MERGE_HEAD" ]; then
 530                rloga='commit (merge)'
 531                PARENTS="-p HEAD "`sed -e 's/^/-p /' "$GIT_DIR/MERGE_HEAD"`
 532        elif test -n "$amend"; then
 533                rloga='commit (amend)'
 534                PARENTS=$(git-cat-file commit HEAD |
 535                        sed -n -e '/^$/q' -e 's/^parent /-p /p')
 536        fi
 537        current="$(git-rev-parse --verify HEAD)"
 538else
 539        if [ -z "$(git-ls-files)" ]; then
 540                echo >&2 'nothing to commit (use "git add file1 file2" to include for commit)'
 541                exit 1
 542        fi
 543        PARENTS=""
 544        rloga='commit (initial)'
 545        current=''
 546fi
 547set_reflog_action "$rloga"
 548
 549if test -z "$no_edit"
 550then
 551        {
 552                echo ""
 553                echo "# Please enter the commit message for your changes."
 554                echo "# (Comment lines starting with '#' will not be included)"
 555                test -z "$only_include_assumed" || echo "$only_include_assumed"
 556                run_status
 557        } >>"$GIT_DIR"/COMMIT_EDITMSG
 558else
 559        # we need to check if there is anything to commit
 560        run_status >/dev/null 
 561fi
 562if [ "$?" != "0" -a ! -f "$GIT_DIR/MERGE_HEAD" -a -z "$amend" ]
 563then
 564        rm -f "$GIT_DIR/COMMIT_EDITMSG" "$GIT_DIR/SQUASH_MSG"
 565        run_status
 566        exit 1
 567fi
 568
 569case "$no_edit" in
 570'')
 571        case "${VISUAL:-$EDITOR},$TERM" in
 572        ,dumb)
 573                echo >&2 "Terminal is dumb but no VISUAL nor EDITOR defined."
 574                echo >&2 "Please supply the commit log message using either"
 575                echo >&2 "-m or -F option.  A boilerplate log message has"
 576                echo >&2 "been prepared in $GIT_DIR/COMMIT_EDITMSG"
 577                exit 1
 578                ;;
 579        esac
 580        git-var GIT_AUTHOR_IDENT > /dev/null  || die
 581        git-var GIT_COMMITTER_IDENT > /dev/null  || die
 582        ${VISUAL:-${EDITOR:-vi}} "$GIT_DIR/COMMIT_EDITMSG"
 583        ;;
 584esac
 585
 586case "$verify" in
 587t)
 588        if test -x "$GIT_DIR"/hooks/commit-msg
 589        then
 590                "$GIT_DIR"/hooks/commit-msg "$GIT_DIR"/COMMIT_EDITMSG || exit
 591        fi
 592esac
 593
 594if test -z "$no_edit"
 595then
 596    sed -e '
 597        /^diff --git a\/.*/{
 598            s///
 599            q
 600        }
 601        /^#/d
 602    ' "$GIT_DIR"/COMMIT_EDITMSG
 603else
 604    cat "$GIT_DIR"/COMMIT_EDITMSG
 605fi |
 606git-stripspace >"$GIT_DIR"/COMMIT_MSG
 607
 608if cnt=`grep -v -i '^Signed-off-by' "$GIT_DIR"/COMMIT_MSG |
 609        git-stripspace |
 610        wc -l` &&
 611   test 0 -lt $cnt
 612then
 613        if test -z "$TMP_INDEX"
 614        then
 615                tree=$(GIT_INDEX_FILE="$USE_INDEX" git-write-tree)
 616        else
 617                tree=$(GIT_INDEX_FILE="$TMP_INDEX" git-write-tree) &&
 618                rm -f "$TMP_INDEX"
 619        fi &&
 620        commit=$(cat "$GIT_DIR"/COMMIT_MSG | git-commit-tree $tree $PARENTS) &&
 621        rlogm=$(sed -e 1q "$GIT_DIR"/COMMIT_MSG) &&
 622        git-update-ref -m "$GIT_REFLOG_ACTION: $rlogm" HEAD $commit "$current" &&
 623        rm -f -- "$GIT_DIR/MERGE_HEAD" "$GIT_DIR/MERGE_MSG" &&
 624        if test -f "$NEXT_INDEX"
 625        then
 626                mv "$NEXT_INDEX" "$THIS_INDEX"
 627        else
 628                : ;# happy
 629        fi
 630else
 631        echo >&2 "* no commit message?  aborting commit."
 632        false
 633fi
 634ret="$?"
 635rm -f "$GIT_DIR/COMMIT_MSG" "$GIT_DIR/COMMIT_EDITMSG" "$GIT_DIR/SQUASH_MSG"
 636
 637cd_to_toplevel
 638
 639if test -d "$GIT_DIR/rr-cache"
 640then
 641        git-rerere
 642fi
 643
 644if test "$ret" = 0
 645then
 646        if test -x "$GIT_DIR"/hooks/post-commit
 647        then
 648                "$GIT_DIR"/hooks/post-commit
 649        fi
 650        if test -z "$quiet"
 651        then
 652                commit=`git-diff-tree --always --shortstat --pretty="format:%h: %s"\
 653                       --summary --root HEAD --`
 654                echo "Created${initial_commit:+ initial} commit $commit"
 655        fi
 656fi
 657
 658exit "$ret"