Aggiungi solo modifiche non di spazi bianchi


343

Ho il mio editor di testo per tagliare automaticamente gli spazi vuoti finali al momento del salvataggio di un file e sto contribuendo a un progetto open source che ha gravi problemi con gli spazi bianchi finali.

Ogni volta che provo a inviare una patch, devo prima ignorare manualmente tutte le modifiche relative esclusivamente agli spazi bianchi, per scegliere solo le informazioni pertinenti. Non solo, ma quando corro di git rebasesolito incontro diversi problemi a causa loro.

Come tale, vorrei poter aggiungere all'indice solo le modifiche non di spazi bianchi, in modo simile git add -p, ma senza dover scegliere tutte le modifiche da solo.

Qualcuno sa come fare questo?

EDIT: non posso cambiare il modo in cui funziona il progetto e hanno deciso, dopo averne discusso sulla mailing list, di ignorarlo.

Risposte:


395

La soluzione @Frew non era proprio quello di cui avevo bisogno, quindi questo è l'alias che ho fatto per lo stesso identico problema:

alias.addnw=!sh -c 'git diff -U0 -w --no-color "$@" | git apply --cached --ignore-whitespace --unidiff-zero -'

Oppure puoi semplicemente eseguire:

git diff -U0 -w --no-color | git apply --cached --ignore-whitespace --unidiff-zero -

Aggiornare

Aggiunte opzioni -U0e, --unidiff-zerorispettivamente, per risolvere i problemi di corrispondenza del contesto, secondo questo commento .

Fondamentalmente applica la patch che verrebbe applicata addsenza modifiche agli spazi bianchi. Noterai che dopo un git addnw your/fileci saranno ancora cambiamenti non messi in scena, sono gli spazi bianchi rimasti.

--No-color non è richiesto ma dato che ho i colori impostati su sempre, devo usarlo. Comunque, meglio prevenire che curare.


7
Questo ha funzionato bene per me, tuttavia ho dovuto usare git apply --ignore-whitespacealtrimenti la patch non si applicava per ovvi motivi.
jupp0r

106
Dovrebbe esserci davvero un'opzione per aggiungere git, come in git add -wquesto caso.
Jarl,

7
Questo mi dà problemi con patch does not applye error while searching for... Qualche idea?
DTI-Matt,

18
non ha funzionato per me. Ho ricevuto un patch does not applyerrore
Jerry Saravia,

13
Se stai ricevendo 'di patch non è riuscita' a causa di spazi in un contesto come punti @bronson fuori, questo comando rivisto opere (Esso genera una patch con nessun contesto): git diff -U0 -w --no-color | git apply --cached --ignore-whitespace --unidiff-zero. Questo non è rischioso perché l'indice è già aggiornato come può essere, quindi è una base affidabile per la patch.
void.pointer

36

Questo funziona per me:

Se vuoi mantenere una scorta, questo funziona

git stash && git stash apply && git diff -w > foo.patch && git checkout . && git apply foo.patch && rm foo.patch

Non mi piace lo stashes, ma io ho incontrato un bug in git + Cygwin dove perdo modifiche, in modo da assicurarsi che roba è andato al reflog almeno Ho creato la seguente:

git add . && git commit -am 'tmp' && git reset HEAD^ && git diff -w > foo.patch && git checkout . && git apply foo.patch && rm foo.patch

Fondamentalmente creiamo un diff che non include i cambiamenti di spazio, ripristiniamo tutti i nostri cambiamenti e quindi applichiamo il diff.


1
+1. Potresti voler fare un git stashcheckout invece di avere un backup delle tue modifiche, almeno fino a quando non viene testato.
Paŭlo Ebermann,

1
Ti ritroverai con un sacco di stash e in pratica non hai davvero bisogno di fare tutto questo. Funziona ma penso che sia un po 'disordinato
Colin Hebert,

3
Sono d'accordo con Colin. Se lo script funziona, non dovrebbe essere necessario creare uno stash. Ciò che potrebbe essere utile considerare è eseguire stash, quindi stash pop. Se necessario, gli stash possono essere recuperati, ma altrimenti non si otterranno molti stash. Questo lascia anche un file extra in giro
Casebash

Che ne dici di saltare i file binari? Quando provo ad applicare lo snippet sopra, ricevo errori che la patch non può essere applicata senza la riga dell'indice completa! Ciò che mi batte è che non ho nemmeno toccato questi file / binari in primo luogo!
tver3305,

1
Penso che alla fine del primo comando "git rm foo.patch" dovrebbe essere semplicemente "rm foo.patch". Altrimenti molto utile grazie.
Jack Casey,

33

Crea un file patch contenente solo le modifiche reali (escluse le righe con solo le modifiche agli spazi bianchi), quindi pulisci l'area di lavoro e applica quel file patch:

git diff> backup
git diff -w> modifiche
git reset --hard
patch <modifiche

Rivedi le differenze rimanenti, quindi adde commitnormalmente.

L'equivalente per Mercurial è fare questo:

hg diff> backup
hg diff -w> modifiche
hg ripristina - tutte
hg import --no-commit modifiche


Che cos'è una domanda "protetta"? e anche io rispondo. Non penso che questo si qualifichi anche come una risposta anch'io perché sembra che la domanda sia stata tirata fuori dal
nulla

4
@jww Il nocciolo della domanda del poster originale è "come evitare di commettere modifiche al solo spazio bianco al controllo del codice sorgente". L'OP sta usando Git, ma questo vale anche per tutti i sistemi di controllo del codice sorgente che abbia mai usato. Questa risposta mostra la procedura corretta se qualcuno utilizza Mercurial. Potrei immaginare che qualcun altro potrebbe anche contribuire a una soluzione per le persone che usano Sublesion, ecc.
Steve Pitchers,

1
@jww e @ pagid: ho modificato la mia risposta in modo specifico per Git, usando lo stesso approccio della mia soluzione per Mercurial. Dal mio punto di vista, StackOverflow è molto più di un altro forum di domande e risposte - ha anche un ruolo di deposito di conoscenze. Le persone diverse dal poster originale potrebbero trarre vantaggio dalle risposte fornite e le loro circostanze possono variare. Ecco perché credo che le risposte che trasmettono un principio generale siano valide, piuttosto che indirizzare solo una singola situazione specifica.
Steve Pitchers,

@Steve - "Ho modificato la mia risposta in modo specifico per Git ..." - perché non hai posto una nuova domanda nel contesto di mercurial, e poi hai aggiunto la tua risposta alla nuova domanda ???
jww

8
Questo è in realtà il più pulito, il più comprensibile e il più indistruttibile degli approcci che ho visto.
Kzqai,

12

La risposta più votata non funziona in tutti i casi, a causa degli spazi bianchi nel contesto della patch in base agli utenti nei commenti.

Ho rivisto il comando come segue:

$ git diff -U0 -w --no-color | git apply --cached --ignore-whitespace --unidiff-zero

Questo genera una patch senza contesto. Non dovrebbe essere un problema poiché la patch ha vita breve.

Alias ​​corrispondente, di nuovo una revisione di ciò che è già stato fornito da altri utenti:

addw = !sh -c 'git diff -U0 -w --no-color "$@" | git apply --cached --ignore-whitespace --unidiff-zero' -

Per ignorare solo i cambiamenti di rientro che ho dovuto usare al --ignore-space-changeposto di -w. git diff -U0 --ignore-space-change --no-color | git apply --cached --unidiff-zero
Andy,

Un avvertimento per non usare questo adorabile trucco senza contesto con --ignore-blank-linesaltrimenti troverai blocchi di diff che vengono riparati con offset errati se alcune delle modifiche allo 'spazio bianco' che stai cercando di ignorare sono rimozioni / aggiunte vuote.
elbeardmorez,

12

Aggiungi quanto segue al tuo .gitconfig:

anw = !git diff -U0 -w --no-color -- \"$@\" | git apply --cached --ignore-whitespace --unidiff-zero "#"

Grazie alla risposta di @Colin Herbert per l'ispirazione.

Sintassi Spiegazione

Il finale #deve essere citato in modo da non essere trattato come un commento all'interno di .gitconfig, ma viene invece passato e viene trattato come un commento all'interno della shell: viene inserito tra la fine git applydell'argomento e gli argomenti forniti dall'utente che gitsi posizionano automaticamente nel fine della riga di comando. Questi argomenti non sono desiderati qui - non vogliamo git applyconsumarli, quindi il carattere di commento precedente. Potresti voler eseguire questo comando GIT_TRACE=1 git anwper vederlo in azione.

Il --segnale termina gli argomenti e consente il caso in cui si abbia un file denominato -wo qualcosa che sembrerebbe un passaggio a git diff.

Le virgolette doppie con escape $@sono necessarie per preservare tutti gli argomenti quotati forniti dall'utente. Se il "personaggio non è sfuggito, verrà consumato dal .gitconfigparser e non raggiungerà la shell.

Nota: .gitconfigalias analisi non riconosce apostrofi come qualcosa di speciale - i suoi personaggi solo speciali sono ", \, \ne ;(al di fuori di una "stringa di -quoted). Questo è il motivo per cui a "deve sempre essere evitato, anche se sembra che sia all'interno di una stringa a virgoletta singola (di cui git è completamente agnostico).

Questo è importante, ad es. se hai un utile alias per eseguire un bashcomando nella radice dell'albero di lavoro. La formulazione errata è:

sh = !bash -c '"$@"' -

Mentre quello corretto è:

sh = !bash -c '\"$@\"' -

Eccellente. Questo mi ha permesso di aggiungere un file alla volta. Oltre ad aggiungere una directory root per un argomento, c'è un modo per far funzionare questo come 'git add -A'?
Chucky,

7

Che ne dici di quanto segue:

git add `git diff -w --ignore-submodules |grep "^[+][+][+]" |cut -c7-`

Il comando all'interno dei backquotes ottiene i nomi dei file con modifiche non di spazi bianchi.


2
o solo git add `git diff -w |grep '^+++' |cut -c7-`se i sottomoduli non vengono utilizzati
karmakaze il

-1

Dovresti prima considerare se lo spazio bianco finale è intenzionale. Molti progetti, tra cui il kernel Linux, Mozilla, Drupal e Kerberos (solo per citarne alcuni dalla pagina di Wikipedia sullo stile) vietano lo spazio bianco finale. Dalla documentazione del kernel Linux:

Ottieni un editor decente e non lasciare spazi bianchi alla fine delle righe.

Nel tuo caso, il problema è il contrario: i precedenti commit (e forse quelli attuali) non hanno seguito questa linea guida.

Scommetto che nessuno vuole davvero lo spazio bianco finale e risolvere il problema potrebbe essere un cambiamento positivo. Anche altri utenti potrebbero riscontrare lo stesso problema. È anche probabile che i contributori che stanno aggiungendo spazi vuoti finali non siano consapevoli di farlo.

Invece di provare a riconfigurare git per ignorare il problema, o disabilitare la funzionalità altrimenti desiderabile nel tuo editor, inizierei con un post nella mailing list del progetto che spiega il problema. Molti editor (e git stesso) possono essere configurati per gestire gli spazi bianchi finali.


16
Non è intenzionale, ma non posso cambiare il modo in cui pensano più di 100 persone che contribuiscono al progetto. A loro non importa, e non accetteranno patch con oltre 1000 modifiche che riguardano solo gli spazi bianchi finali. Conoscono il problema e hanno deciso di ignorarlo. Questa discussione è già avvenuta nell'elenco ed è stata chiusa. In questo caso, sono io che devo adattarmi a loro.
Edu Felipe,

19
Quindi configura il tuo editor in modo tale che non tagli gli spazi vuoti finali quando lavori sul codice di questo progetto.
Jamessan,

-2

Ho trovato un hook pre-commit git che rimuove gli spazi bianchi finali . Tuttavia, se non riesci a convincere gli altri a usarlo, potrebbe non essere una soluzione valida.

  #!/bin/sh

  if git-rev-parse --verify HEAD >/dev/null 2>&1 ; then
     against=HEAD
  else
     # Initial commit: diff against an empty tree object
     against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
  fi
  # Find files with trailing whitespace
  for FILE in `exec git diff-index --check --cached $against -- | sed '/^[+-]/d' | sed -r 's/:[0-9]+:.*//' | uniq` ; do
     # Fix them!
     sed -i 's/[[:space:]]*$//' "$FILE"
  done
  exit

4
Questa domanda è: come conservare gli spazi bianchi finali.
Douglas,

@Douglas: probabilmente si potrebbe usare questa risposta per creare un commit su un ramo temporaneo, eseguire il commit della patch reale lì e selezionare in qualche modo il diff solo nel ramo funzionante ...
Tobias Kienzler,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.