2011-07-09 94 views
8

有時候從肌肉記憶中,我運行了git commit -a,當我有一些文件或文件的一部分被仔細地分階段準備提交時,導致我失去了謹慎的分段操作。做git commit時發出警告-a如果發生了某些事情

有沒有辦法讓git commit -a警告如果有什麼(文件或補丁)目前上演?

(顯然,我應該只使用-a較少,以減輕我的問題,但我的問題的立場。)

+0

只是好奇:爲什麼你使用'-a',當你不想使用它?我建議完全用'commit -a'來克服,並使用'git add。代替&& git commit'。我知道這是兩條命令,但這樣幾乎不可能錯誤地添加每一個變化 – KingCrunch

回答

0

我不知道有任何自動方式,但手動它這樣做只是想在這個問題: How do I show the changes which have been staged?

基本上是: git diff --cached

+1

是的,這不是一個我不知道打字的問題,而是我的手指不會聽我說,有時還會堅持當我沒有給予足夠的關注時,做'-a'。 ;) –

+0

heh是啊我知道你的意思:) – JohnKlehm

1

添加pre-commit胡克在你的回購,有類似下面:

#!/bin/sh 
echo "Make sure you haven't used the -a flag or verify git diff --cached returns nothing" 
echo "Run commit again with --no-verify if ok to proceed" 
exit 1 

這應該有助於你克服你的「肌肉記憶」。

不幸的是,預先提交鉤子不能強大到足以執行更多檢查(例如,如果您已將提供-a參數提交給提交)。另外,當您執行-a時,預先提交鉤子將看起來好像所有文件被執行後,儘管在執行後,你會看到它們是未執行的。所以你不能區分你之前上演過的作品和因爲-a而上演的作品。

1

您可以使用自己喜歡的腳本語言來創建git2命令,該命令將檢查您是否在運行參數commit -a。如果是這種情況,運行/usr/bin/git status --porcelain並檢查索引是否有一些變化(瓷格式的輸出更容易解析,我的第一個猜測是運行它通過grep '^[AMD]'並檢查它是否找到了某些東西。現在,您可以打印警告並退出,或者運行/usr/bin/git,所有原始參數都會繼續運行,就像沒有git2一樣(這也是您如果未使用commit -a運行時所要做的)

下面是Perl中的示例這混帳要求反正):

#!/usr/bin/env perl 

use strict; 
use warnings; 

my %aliases = map { split(/\n/, $_, 2) } 
    split /\0/, 
    `git config -z --get-regexp alias\\.`; 

my %commit_aliases = ((commit => 1), 
    map { s/alias\.//; $_ => 1 } 
    grep $aliases{$_} =~ /^commit\b/, 
    keys %aliases); 

my ($command, @args) = @ARGV; 

if ($commit_aliases{$command} && $args[0] =~ /^-a|^--all/) { 
    my @staged = grep /^M/, split /\0/, `git status -z`; 
    if (@staged) { 
     print "There are staged changes, are you sure you want to commit all? (y/N) "; 
     chomp(my $answer = <STDIN>); 
     if ($answer =~ /^y/i) { 
     run_command() 
     } 
    } else { 
     run_command() 
    } 
} else { 
    run_command() 
} 

sub run_command { 
    system 'git', $command, @args; 
    exit $? >> 8; 
} 

然後,創建一個bash別名alias git2 git和你所有的設置

+1

剛剛在perl中添加了一個例子;這並不完美,但它確實工作得很好。 (如果你的別名有-a或者你做了git ci -m'foo'-a) –

2

不幸的是,Git不允許別名來覆蓋現有的命令,否則你可以很容易地通過別名添加這個功能。

但是,你可以在那裏獲得一部分。這將需要重新訓練自己輸入的東西,而不是git commit —或許git c

這裏是你如何能做到這一點:

  1. 把下面的shell代碼在腳本文件的地方(例如,,/path/to/commit-wrapper

    #!/bin/sh 
    
    # avoid echo because some implementations treat backslashes specially 
    log() { printf '%s\n' "$*"; } 
    error() { log "ERROR: $*" >&2; } 
    fatal() { error "$*"; exit 1; } 
    
    check_for_staged() { 
        git diff-index --cached --quiet HEAD || { 
    
         # simply exit with an error if run non-interactively 
         tty >/dev/null \ 
          || fatal "don't use '$1' when you have staged changes" 
    
         # this script is being run interactively; prompt the user to 
         # continue 
         error "'$1' option used when there are staged changes" 
         while true; do 
          printf 'Continue anyway? [y/N] ' >&2 
          read answer || { printf '\n'; answer=N; } 
          [ -n "${answer}" ] || answer=N 
          case ${answer} in 
           y|Y) break;; 
           n|N) echo "aborted" >&2; exit 1;; 
           *) error "Please answer 'y' or 'n'.";; 
          esac 
         done 
        } 
    } 
    
    # TODO: use 'git rev-parse --parseopt' to reliably detect '-a' (e.g., 
    # to properly handle invocations such as 'git commit -sa') 
    for i in "[email protected]"; do 
        case ${i} in 
         --) break;; 
         -a|--all) check_for_staged "${i}"; break;; 
        esac 
    done 
    
    git commit "[email protected]" 
    
  2. 使文件可執行:chmod a+x /path/to/commit-wrapper
  3. 設置您的別名:git config --global alias.c '!/path/to/commit-wrapper'
  4. 使用git c而不是git commit

如果Git被更改爲允許現有命令的別名,請將最後一行更改爲"$(git --exec-path)"/git-commit "[email protected]"以避免無限循環。

相關問題