在做git commit时发出警告
有时候从肌肉记忆中,我运行git commit -a
当我有一些文件或文件的一部分仔细地上演并准备提交时,导致我失去了谨慎的分段操作。
有没有办法让git commit -a
如果有任何东西(文件或补丁)目前上演警告?
(很明显,我应该使用-a
减少来缓解我的问题,但是我的问题仍然存在。)
不幸的是,Git不允许别名覆盖现有的命令,否则您可以通过别名轻松添加此功能。
但是,你可以在那里获得一部分。 这将需要重新训练自己键入一些东西,而不是git commit
git c
。
你可以这样做:
将下面的shell代码放在某个脚本文件中(例如, /path/to/commit-wrapper
)
#!/bin/sh
# avoid echo because some implementations treat backslashes specially
log() { printf '%sn' "$*"; }
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 "$@"
chmod a+x /path/to/commit-wrapper
git config --global alias.c '!/path/to/commit-wrapper'
git c
而不是git commit
。 如果Git被更改为允许现有命令的别名,请将最后一行更改为"$(git --exec-path)"/git-commit "$@"
以避免无限循环。
在回购库中添加一个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
而上演的文件。
你可以使用你最喜欢的脚本语言来创建git2
命令,它会检查你是否用参数commit -a
来运行它。 如果是这样的话,运行/usr/bin/git status --porcelain
并检查是否有一些对索引的更改(瓷格式的输出更容易解析,我的第一个猜测是通过grep '^[AMD]'
并检查它是否找到了一些东西,现在,你可以打印一个警告然后退出,或者运行/usr/bin/git
所有原始参数继续,就像没有git2一样(这也是你如果避难的话没有与提交运行-a)。
下面是Perl中的一个例子(无论如何git都需要这样做):
#!/usr/bin/env perl
use strict;
use warnings;
my %aliases = map { split(/n/, $_, 2) }
split / /,
`git config -z --get-regexp alias.`;
my %commit_aliases = (( commit => 1 ),
map { s/alias.//; $_ => 1 }
grep $aliases{$_} =~ /^commitb/,
keys %aliases);
my ($command, @args) = @ARGV;
if ($commit_aliases{$command} && $args[0] =~ /^-a|^--all/) {
my @staged = grep /^M/, split / /, `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
,你就全部设置好了。