2011-07-09 28 views
8

A veces, a partir de la memoria muscular, ejecuto git commit -a cuando tengo algunos archivos o partes de archivos cuidadosamente organizados y listos para cometer, lo que hace que pierda mi cuidadosa acción de puesta en escena.Avisar cuando se hace git commit -a si algo se organiza

¿Hay alguna manera de hacer que git commit -a advierta si hay algo (archivo o parche) actualmente en escena?

(claro que yo sólo debería utilizar -a menos para aliviar mi problema, pero mi pregunta se levanta.)

+0

Simplemente curioso: ¿Por qué usa '-a' cuando no quiere usarlo? Recomiendo superar con 'commit -a' por completo y usar' git add. && git commit' en su lugar. Esos son dos comandos, lo sé, pero de esta manera es casi imposible agregar cada cambio por error – KingCrunch

Respuesta

0

Yo no sé de ninguna manera automática, sino que de forma manual ya está hecho al igual que en esta pregunta: How do I show the changes which have been staged?

que es esencialmente: git diff --cached

+1

Sí, no es tanto cuestión de que yo no sepa qué escribir, sino que mis dedos no me escuchen y, a veces, insistan en haciendo ''A' cuando no estoy prestando suficiente atención. ;) –

+0

Heh, sí, sé lo que quieres decir :) – JohnKlehm

1

Añadir un Hooke pre-commit en tu repositorio, con algo parecido a continuación:

#!/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 

Eso debería ayudarlo a superar su "memoria muscular".

Desafortunadamente, antes de comprometerse gancho no puede ser lo suficientemente potente como para hacer más comprobaciones (como si se hubiera suministrado el argumento -a a la confirmación.) Además, cuando haces -a, el gancho pre-commit verán como si toda la los archivos se organizaron, aunque después de la ejecución, los verá como no fragmentados. Por lo tanto, no puede diferenciar entre lo que había organizado previamente y los archivos montados a causa del -a.

1

Puede usar su lenguaje de scripting favorito para crear el comando git2, que comprobará si lo está ejecutando con los argumentos commit -a. Si ese es el caso, ejecute /usr/bin/git status --porcelain y compruebe si hay algunos cambios en el índice (la salida con formato de porcelana es más fácil de analizar, mi primera conjetura sería ejecutarla a través de grep '^[AMD]' y verificar si encontró algo. Ahora, puede imprimir una advertencia y salir, o ejecutar /usr/bin/git que todos los argumentos originales para continuar como si no hubiera git2 (que también es lo que debes hacer si no has sido ejecutado con commit -a).

Aquí hay un ejemplo en Perl (git, que requiere de todos modos):

#!/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; 
} 

a continuación, cree un alias de fiesta alias git2 git y ya está todo listo

.
+1

Acabo de añadir un ejemplo en Perl; no es perfecto, pero funciona muy bien. (No funciona si su alias tiene -a en él o si lo hace git ci -m 'foo' -a) –

2

Desafortunadamente, Git no permite que los alias anulen los comandos existentes, de lo contrario, podría agregar fácilmente esta funcionalidad mediante un alias.

Pero, puede obtener parte camino allí. Se requeriría volver a capacitarse para escribir algo en lugar de git commit — quizás git c.

Así es como podría hacerlo:

  1. ponga el siguiente código de depósito en un archivo de script en alguna parte (por ejemplo,, /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. hacer que el archivo ejecutable: chmod a+x /path/to/commit-wrapper
  3. Configure su alias: git config --global alias.c '!/path/to/commit-wrapper'
  4. Uso git c en lugar de git commit.

Si Git se cambia alguna vez para permitir alias para los comandos existentes, cambie la última línea para decir "$(git --exec-path)"/git-commit "[email protected]" para evitar un bucle infinito.