Alle Dateien zu einem Commit hinzufügen, außer einer einzelnen Datei?

571

Ich habe eine Reihe von Dateien in einem Änderungssatz, möchte jedoch eine einzelne geänderte Datei ignorieren. Sieht danach so aus git status:

# modified:   main/dontcheckmein.txt
# deleted:    main/plzcheckmein.c
# deleted:    main/plzcheckmein2.c
...

Gibt es eine Möglichkeit git add, die eine Textdatei, die ich nicht berühren möchte , einfach zu ignorieren? Etwas wie:

git add -u -except main/dontcheckmein.txt
user291701
quelle

Antworten:

851
git add -u
git reset -- main/dontcheckmein.txt
Ben Jackson
quelle
28
Wie schließe ich den gesamten Ordner aus? - Haupt oder Haupt / oder Haupt / *?
Alan Coromano
8
@MariusKavansky Sie können alle diese Formulare verwenden. Wenn Sie es verwenden, müssen main/*Sie --davor hinzufügen , um git wissen zu lassen, dass es sich um einen Pfad handelt. Die beiden anderen Varianten funktionieren ohne die beiden Striche. (Getestet in der Eingabeaufforderung unter Windows 7 mit msysGit)
dennisschagt
2
Wenn Sie einige Ordner ausschließen möchten, die eine große Anzahl von Dateien oder anderen Ordnern enthalten, fügen Sie sie vorübergehend Ihrem Gitignore hinzu. Das anschließende Ausführen eines git resetfür diese Ordner funktioniert weiterhin, aber das Hinzufügen der großen Ordner dauert lange.
Michael Trouw
2
Es gibt also keinen Einzeiler?
BroVic
5
@ Ben Jackson wäre nett, jede Zeile zu kommentieren, findest du nicht?
ed1nh0
140

1) Um Änderungen an einer einzelnen bereits versionierten Datei zu ignorieren

git update-index --assume-unchanged "main/dontcheckmein.txt"

und das rückgängig zu machen git update-index --no-assume-unchanged "main/dontcheckmein.txt"

Github-Dokumente zum Ignorieren von Dateien

2) Um eine bestimmte einzelne Datei vollständig zu ignorieren und zu verhindern, dass sie im Repository erstellt wird

Schauen Sie sich zunächst diesen Stackoverflow-Beitrag an: Git Global Ignorieren funktioniert nicht

In .gitignore, fügen Sie den relativen Pfad zur Datei ohne führende ./.

Wenn sich Ihre Datei also in MyProject/MyFolder/myfile.txtbefindet (wo .gitsich auch im MyProjectOrdner befindet), fügen Sie MyFolder/myfile.txtsie Ihrer at- .gitignoreDatei hinzu.

Sie können bestätigen, welche Regeln mit Ignorieren über verknüpft sind git check-ignore "MyFolder/myfile.txt"

Über globales Ignorieren

Dieser Link spricht darüber ~/.gitignore_global, aber die Datei bezieht sich auf Ihr Projekt. Also, wenn Sie das setzen ausschließen Muster MyFolder/myfile.txtin ~/.gitignore_global, es wird funktionieren , aber nicht viel Sinn machen ...

Auf der anderen Seite, wenn Sie Setup - Projekt mit git config core.excludesfile .gitignoredem .gitignoreist in MyProject, wird die lokale Datei überschreiben ~/.gitignore_global, die haben sehr nützliche Regeln ...

So, jetzt, ich denke , es ist am besten, einige Skript machen Sie Ihren mischen .gitignoremit ~/.gitignore_globalbei .gitignore.

Eine letzte Warnung
Wenn sich die Datei, die Sie ignorieren möchten, bereits im Repository befindet, funktioniert diese Methode nur, wenn Sie dies tun: Sichern Sie git rm "MyFolder/myfile.txt"sie jedoch zuerst, da sie auch lokal entfernt wird! Sie können es später wieder kopieren ...

Wassermann-Kraft
quelle
5
Sie können git rm --cached MyFolder/myyfile.txtdie Datei verwenden , um sie aus dem Repository zu entfernen, aber lokal aufbewahren. Erklärung auf help.github.com
dennisschagt
87

Für eine Datei

git add -u
git reset -- main/dontcheckmein.txt

Für einen Ordner

git add -u
git reset -- main/*
Rituraj ratan
quelle
9
warum ist das -u notwendig? warum nicht git add . && git reset -- main/*?
2
Die Option -u aktualisiert den Index genau dort, wo bereits ein Eintrag vorhanden ist, der mit <Pfadspezifikation> übereinstimmt. Dadurch werden Indexeinträge entfernt und an den Arbeitsbaum angepasst, es werden jedoch keine neuen Dateien hinzugefügt. Wenn bei Verwendung der Option -u keine <Pfadspezifikation> angegeben wird, werden alle nachverfolgten Dateien im gesamten Arbeitsbaum aktualisiert (alte Versionen von Git werden verwendet, um die Aktualisierung auf das aktuelle Verzeichnis und seine Unterverzeichnisse zu beschränken).
Farhad Mammadli
6
Kann jemand erklären, warum das -u in einer Sprache notwendig ist, die Nicht-Git-Profis verstehen werden?
Patrick
2
-u wird verwendet, um auf Ihren aktuellen Zweig zu verweisen, zu dem Sie pushen. Sie müssen git push origin masterIhren nächsten Push nicht mehr eingeben, nur git pushund Git wird wissen, dass es sich um einen Master-Zweig handelt. Ich hoffe es hilft.
Pepeng Hapon
69

gitUnterstützt jetzt exclude certain paths and filesdurch Pathspec Magic :(exclude)und seine Kurzform :!. So können Sie es einfach mit dem folgenden Befehl erreichen.

git add --all -- :!main/dontcheckmein.txt
git add -- . :!main/dontcheckmein.txt

Eigentlich können Sie mehr angeben:

git add --all -- :!path/to/file1 :!path/to/file2 :!path/to/folder1/*
git add -- . :!path/to/file1 :!path/to/file2 :!path/to/folder1/*
Katzenaugen
quelle
1
Die beste Antwort, danke! Zumindest für meinen Fall: Ich musste nur einen Dateityp ausschließen.
Andre Polykanine
15
Das ist ausgezeichnet! Beachten Sie, dass Sie unter Linux die :!...Klauseln zitieren müssen , damit sich die Shell nicht beschwert. So zum Beispiel : git add --all -- ':!path/to/file1' ':!path/to/file2' ':!path/to/folder1/*'.
Martin_W
Gibt es so etwas :!/path/to/(file1|file2)?
seeker_of_bacon
Dies kollidiert mit etwas in zsh, funktioniert bei mir unter macOS und dem neuesten Git nicht.
Merlin
1
Kann jemand darauf hinweisen, wo dies offiziell dokumentiert ist?
samurai_jane
20

Während Ben Jackson Recht hat, dachte ich, ich würde hinzufügen, wie ich diese Lösung auch verwendet habe. Im Folgenden finden Sie ein sehr einfaches Skript, das ich verwende (das ich gitadd nenne), um alle Änderungen hinzuzufügen, mit Ausnahme einiger weniger, die ich in einer Datei mit dem Namen .gittrackignore(gitignore) aufgelistet habe.

#!/bin/bash
set -e

git add -A
git reset `cat .gittrackignore`

Und so .gittrackignoresieht meine Strömung aus.

project.properties

Ich arbeite an einem Android-Projekt, das ich bei der Bereitstellung über die Befehlszeile kompiliere. Dieses Projekt hängt von SherlockActionBar ab, daher muss es in project.properties referenziert werden, aber das beeinträchtigt die Kompilierung. Jetzt tippe ich einfach gitaddalle Änderungen an git ein und füge sie hinzu, ohne jedes Mal project.properties entfernen zu müssen.

Anthony Naddeo
quelle
Ich wusste --bis zu Ihrem Kommentar nicht, was war. Laut den Manpages ist es optional und ändert das Ergebnis des Befehls nicht (zumindest in diesem Fall). Diese Frage scheint dies zu unterstützen: stackoverflow.com/questions/17800994/… . Korrigieren Sie mich, wenn ich falsch liege, aber es scheint, dass es bedeutet, "alles danach --als Argumente zu behandeln, nicht als Optionen / Schalter"
Anthony Naddeo
Gute Verwendung von --in git checkoutsehe ich in dieser Frage. Ich wusste nicht, was der doppelte Strich war, bis auch dieser Austausch von uns. Ich frage mich, ob sich die git checkoutMehrdeutigkeit zwischen Zweigen und Dateien auch in dieser oder einer anderen Form auswirken könnte git reset.
Giulio Piancastelli
10

Um die Änderung in der Datei zu behalten, aber nicht zu verpflichten, habe ich dies getan

git add .

git reset -- main/dontcheckmein.txt

git commit -m "commit message"

um zu überprüfen, ob die Datei ausgeschlossen ist, tun Sie

git status

gsumk
quelle
4

Verwenden Sie git add -Adiese Option , um alle geänderten und neu hinzugefügten Dateien gleichzeitig hinzuzufügen.

Beispiel

git add -A
git reset -- main/dontcheckmein.txt
Dhanuka Nuwan
quelle
4
git add .
git reset main/dontcheckmein.txt
Daniel Danielecki
quelle
2

Versuche dies:

git checkout -- main/dontcheckmein.txt
Abdullah Aman
quelle
1
Dadurch werden alle Änderungen von main / dontcheckmein.txt rückgängig gemacht.
Gsumk
stackoverflow.com/questions/41101998/… Dies macht die Änderungen rückgängig
Dhanapal
1

Für den speziellen Fall in der Frage wäre es am einfachsten, alle Dateien mit der Erweiterung .c hinzuzufügen und alles andere wegzulassen :

git add *.c

Von git-scm (oder / und man git add):

git add <Pfadspezifikation>…

Dateien, aus denen Inhalte hinzugefügt werden sollen. Fileglobs (zB * .c) können angegeben werden, um alle übereinstimmenden Dateien hinzuzufügen. <...>

Beachten Sie, dass dies bedeutet, dass Sie auch Folgendes tun können:

git add **/main/*

um alle Dateien (die nicht ignoriert werden) hinzuzufügen, die sich im mainOrdner befinden. Sie können sogar mit ausgefeilteren Mustern wild werden:

git add **/s?c/*Service*

Oben werden alle Dateien hinzugefügt, die sich im s(any char)cOrdner befinden und Serviceirgendwo in ihrem Dateinamen enthalten sind.

Offensichtlich sind Sie nicht auf ein Muster pro Befehl beschränkt. Das heißt, Sie könnten git bitten, alle Dateien mit der Erweiterung .c und .h hinzuzufügen :

git add *.c *.h

Über diesen Link erhalten Sie möglicherweise weitere Ideen für Glob-Muster.

Ich finde es besonders nützlich, wenn ich viele Änderungen vornehme, aber dennoch möchte, dass meine Commits atomar bleiben und schrittweise Prozesse widerspiegeln, anstatt eine Vielzahl von Änderungen, an denen ich gerade arbeite. Natürlich überwiegen irgendwann die Kosten für die Erstellung ausgefeilter Muster die Kosten für das Hinzufügen von Dateien mit einfacheren Methoden oder sogar jeweils einer Datei. Die meiste Zeit bin ich jedoch leicht in der Lage, genau die Dateien, die ich benötige, mit einem einfachen Muster zu lokalisieren und alles andere auszuschließen.

Übrigens müssen Sie möglicherweise Ihre Glob-Muster zitieren, damit sie funktionieren, aber das war bei mir nie der Fall.

Cegas
quelle
0

Ich benutze git add --patchziemlich viel und wollte so etwas, um zu vermeiden, dass ich dständig durch dieselben Dateien schlagen muss . Ich habe ein paar sehr hackige Aliase zusammengestellt, um die Arbeit zu erledigen:

[alias]
    HELPER-CHANGED-FILTERED = "!f() { git status --porcelain | cut -c4- | ( [[ \"$1\" ]] && egrep -v \"$1\" || cat ); }; f"
    ap                      = "!git add --patch -- $(git HELPER-CHANGED-FILTERED 'min.(js|css)$' || echo 'THIS_FILE_PROBABLY_DOESNT_EXIST' )"

In meinem Fall wollte ich nur bestimmte minimierte Dateien die ganze Zeit ignorieren, aber Sie könnten dafür sorgen, dass eine Umgebungsvariable wie $GIT_EXCLUDE_PATTERNfür einen allgemeineren Anwendungsfall verwendet wird.

Chris
quelle
0

Zu übernehmende Änderungen: (Verwenden Sie "git reset HEAD ...", um die Bühne zu verlassen)

Colin Rickels
quelle
0

Sie können dies versuchen: git add * && git reset main/dontcheckmein.txt

Rodrigo
quelle