有時候從肌肉記憶中,我運行了git commit -a
,當我有一些文件或文件的一部分被仔細地分階段準備提交時,導致我失去了謹慎的分段操作。做git commit時發出警告-a如果發生了某些事情
有沒有辦法讓git commit -a
警告如果有什麼(文件或補丁)目前上演?
(顯然,我應該只使用-a
較少,以減輕我的問題,但我的問題的立場。)
有時候從肌肉記憶中,我運行了git commit -a
,當我有一些文件或文件的一部分被仔細地分階段準備提交時,導致我失去了謹慎的分段操作。做git commit時發出警告-a如果發生了某些事情
有沒有辦法讓git commit -a
警告如果有什麼(文件或補丁)目前上演?
(顯然,我應該只使用-a
較少,以減輕我的問題,但我的問題的立場。)
我不知道有任何自動方式,但手動它這樣做只是想在這個問題: How do I show the changes which have been staged?
基本上是: git diff --cached
是的,這不是一個我不知道打字的問題,而是我的手指不會聽我說,有時還會堅持當我沒有給予足夠的關注時,做'-a'。 ;) –
heh是啊我知道你的意思:) – JohnKlehm
添加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
而上演的作品。
您可以使用自己喜歡的腳本語言來創建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
和你所有的設置
剛剛在perl中添加了一個例子;這並不完美,但它確實工作得很好。 (如果你的別名有-a或者你做了git ci -m'foo'-a) –
不幸的是,Git不允許別名來覆蓋現有的命令,否則你可以很容易地通過別名添加這個功能。
但是,你可以在那裏獲得一部分。這將需要重新訓練自己輸入的東西,而不是git commit
—或許git c
。
這裏是你如何能做到這一點:
把下面的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]"
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 "[email protected]"
以避免無限循環。
只是好奇:爲什麼你使用'-a',當你不想使用它?我建議完全用'commit -a'來克服,並使用'git add。代替&& git commit'。我知道這是兩條命令,但這樣幾乎不可能錯誤地添加每一個變化 – KingCrunch