在进行git commit时发出警告-a如果某些事情被暂存

时间:2011-07-09 00:39:36

标签: git

有时从肌肉记忆中,当我有一些文件或部分文件小心地上演并准备好提交时,我运行git commit -a,导致我失去了我的谨慎的分期行动。

如果当前有任何内容(文件或补丁)上架,有没有办法让git commit -a发出警告?

(显然我应该少用-a来缓解我的问题,但我的问题仍然存在。)

4 个答案:

答案 0 :(得分: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 "$@"; do
        case ${i} in
            --) break;;
            -a|--all) check_for_staged "${i}"; break;;
        esac
    done
    
    git commit "$@"
    
  2. 使文件可执行:chmod a+x /path/to/commit-wrapper
  3. 设置别名:git config --global alias.c '!/path/to/commit-wrapper'
  4. 使用git c代替git commit
  5. 如果Git被更改为允许现有命令的别名,请将最后一行更改为"$(git --exec-path)"/git-commit "$@"以避免无限循环。

答案 1 :(得分:1)

在您的仓库中添加pre-commit hooke,如下所示:

#!/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而暂存的文件。

答案 2 :(得分:1)

您可以使用自己喜欢的脚本语言来创建git2命令,该命令将检查您是否使用参数commit -a运行它。如果是这种情况,请运行/usr/bin/git status --porcelain并检查索引是否有一些更改(瓷格式输出更容易解析,我的第一个猜测是通过grep '^[AMD]'运行它并检查它是否现在,您可以打印警告并退出,或者运行/usr/bin/git所有原始参数继续,就像没有git2一样(如果你没有使用commit运行,那也是你做的事情-a )。

以下是Perl中的一个示例(无论如何git都需要):

#!/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,然后就可以了。

答案 3 :(得分:0)

我不知道任何自动方式,但手动完成就像在这个问题中一样: How do I show the changes which have been staged?

本质上是: git diff --cached