Übernehmen Sie nur einen Teil einer Datei in Git


2764

Wie kann ich nur einige der Änderungen festschreiben, wenn ich Änderungen an einer Datei in Git vornehme?

Wie kann ich beispielsweise nur 15 von 30 Zeilen festschreiben, die in einer Datei geändert wurden?


3
verwandter stackoverflow.com/q/34609924/52074 : Wenn Sie ein Stück in kleinere Stücke aufteilen müssen.
Trevor Boyd Smith

Zusammenfassung: in Bezug auf die Fähigkeit: git gui= git add -e> git add -i -p; in Bezug auf Komfort: git gui> git add -i -p> git add -e. Also: Wählen git guiSie, wenn Sie Zugriff auf X git add -i -phaben. git add -e
Wählen

Antworten:


3687

Sie können verwenden git add --patch <filename>(oder -pkurz), und git beginnt, Ihre Datei in das zu zerlegen, was es für sinnvolle "Hunks" (Teile der Datei) hält. Sie werden dann mit folgender Frage aufgefordert:

Stage this hunk [y,n,q,a,d,/,j,J,g,s,e,?]?

Hier ist eine Beschreibung jeder Option:

  • y Stellen Sie dieses Stück für das nächste Commit bereit
  • n Stellen Sie dieses Stück nicht für das nächste Commit bereit
  • qVerlassen; Stellen Sie dieses Stück oder eines der verbleibenden Stücke nicht in Szene
  • a Stellen Sie dieses Stück und alle späteren Stücke in der Datei bereit
  • d Stellen Sie dieses Stück oder eines der späteren Stücke in der Datei nicht bereit
  • g Wählen Sie ein Stück aus, zu dem Sie gehen möchten
  • / Suche nach einem Stück, das dem angegebenen regulären Ausdruck entspricht
  • j Lass dieses Stück unentschlossen, siehe nächstes unentschiedenes Stück
  • J Lass dieses Stück unentschlossen, siehe nächstes Stück
  • k Lassen Sie dieses Stück unentschlossen, siehe vorheriges unentschlossenes Stück
  • K Lassen Sie dieses Stück unentschlossen, siehe vorheriges Stück
  • s Teilen Sie das aktuelle Stück in kleinere Stücke auf
  • e Bearbeiten Sie das aktuelle Stück manuell
  • ? Hunk-Hilfe drucken

Wenn sich die Datei noch nicht im Repository befindet, können Sie dies zuerst tun git add -N <filename>. Danach können Sie fortfahren git add -p <filename>.

Danach können Sie verwenden:

  • git diff --staged um zu überprüfen, ob Sie die richtigen Änderungen vorgenommen haben
  • git reset -p irrtümlich hinzugefügte Kerle zu entfernen
  • git commit -v um Ihr Commit anzuzeigen, während Sie die Commit-Nachricht bearbeiten.

Beachten Sie, dass dies ein großer Unterschied zu dem git format-patchBefehl ist, mit dem Festschreibungsdaten in .patchDateien analysiert werden sollen.

Referenz für die Zukunft: Git Tools - Interactive Staging


83
Es kann nützlich sein zu beachten, dass dies -p/--patcheine Verknüpfung zu der Patch-Aktion innerhalb des -i/--interactiveBefehls ist, die den nützlichen interaktiven Modus initiiert .
TutuDajuju

5
> Was passiert, wenn diese Datei bereits bereitgestellt ist? Es werden nur nicht bereitgestellte Änderungen angezeigt. Gleich wie git diff.
Eugen Konkov

3
Wie kann ich das aktuelle Stück manuell bearbeiten? Ich weiß nicht, was ich tun soll, nachdem ich e eingegeben habe.
Hunsu

23
Nach dem Drücken ekönnen Sie das Stück manuell bearbeiten, indem Sie es ersetzen +oder -durch#
veksen

1
Das ist großartig, aber wie schiebe ich es jetzt tatsächlich? wenn ich es mache git pushsagt es schon aktuell. und wenn ich das tue, git diffsehe ich die Kerle, zu denen ich gesagt nhabe. Wenn ich das tue, git diff --stagedsehe ich das Commit, das ich pushen möchte. Angenommen, ich kann das Commit pushen, wie lösche ich die Hunks, zu denen ich gesagt nohabe?
Chovy

250

Sie können git add --interactiveoder verwenden und dann ( nicht ); Siehe Interaktiver Modus in der git-add- Manpage oder folgen Sie einfach den Anweisungen.git add -p <file>git commit git commit -a

Modern Git hat auch git commit --interactive(und git commit --patch, die Abkürzung zur Patch-Option im interaktiven Commit).

Wenn Sie es lieber über die GUI tun, können Sie git-gui verwenden . Sie können einfach Chunks markieren, die in Commit enthalten sein sollen. Ich persönlich finde es einfacher als zu benutzen git add -i. Andere Git-GUIs wie QGit oder GitX verfügen möglicherweise ebenfalls über diese Funktionalität.


1
Interessanterweise hatte windows.github.com Unterstützung für teilweise Datei-Commits, scheint diese aber kürzlich gelöscht zu haben.
Juri

1
@Juri Ich denke, die Unterstützung für partielle Datei-Commits ist wieder da.
Ela782

@Juri Gern geschehen. Ich habe eigentlich nie bemerkt, dass es dort schon einmal war - ich habe es letzte Woche gesehen und dachte "Oh, was für eine erstaunliche neue Funktion"! :-)
Ela782

1
Heutzutage leitet windows.github.com auf den umbenannten GitHub Desktop um, der besser als die Git-GUI ist und teilweise Festschreibungen unterstützt ... aber keine Festschreibungssignierung unterstützt. Seufzer.

147

git gui bietet diese Funktionalität in der Diff-Ansicht. Klicken Sie einfach mit der rechten Maustaste auf die Zeile (n), an der Sie interessiert sind, und Sie sollten den Menüpunkt "Diese Zeile zum Festschreiben bereitstellen" sehen.


13
Für komplexe Patches ist dies normalerweise der schnellste Ansatz für mich.
hochl

7
Dies ist eine sehr effiziente und intuitive Methode, um Änderungen am Staging-Bereich feinkörnig hinzuzufügen. Es können auch mehrere Zeilen ausgewählt werden, und alle Änderungen innerhalb dieser Auswahl werden hinzugefügt.
Jox

Beachten Sie, dass dies nicht der gitkFall ist , aber in Git Bash für Windows enthalten ist. Sie sollten einen Startmenüeintrag dafür haben oder können ihn mit dem Befehl starten git gui. Es gibt auch stage this hunkwas wahrscheinlich nützlicher ist als stage this line. Könnte neu sein, da diese Antwort vor 10 Jahren erstellt wurde.
Chris

82

Ich glaube das git add -e myfile ist der einfachste Weg (zumindest meine Präferenz), da dadurch einfach ein Texteditor geöffnet wird und Sie auswählen können, welche Zeile Sie inszenieren möchten und welche nicht. Zu Bearbeitungsbefehlen:

hinzugefügter Inhalt:

Der hinzugefügte Inhalt wird durch Zeilen dargestellt, die mit "+" beginnen. Sie können das Bereitstellen von Hinzufügungszeilen verhindern, indem Sie sie löschen.

entfernter Inhalt:

Entfernter Inhalt wird durch Zeilen dargestellt, die mit "-" beginnen. Sie können das Staging ihrer Entfernung verhindern, indem Sie das "-" in ein "" (Leerzeichen) konvertieren.

geänderter Inhalt:

Geänderter Inhalt wird durch "-" Zeilen (Entfernen des alten Inhalts) gefolgt von "+" Zeilen (Hinzufügen des Ersatzinhalts) dargestellt. Sie können das Staging der Änderung verhindern, indem Sie "-" Zeilen in "" konvertieren und "+" Zeilen entfernen. Beachten Sie, dass das Ändern nur der Hälfte des Paares zu verwirrenden Änderungen des Index führen kann.

Alle Details zu git addsind auf verfügbargit --help add


7
Dies wäre nützlicher, wenn es irgendwo eine klare Erklärung dafür gäbe, wie diese Zeilen tatsächlich ausgewählt werden (dh die tatsächlich einzugebenden Befehle). Ich konnte keinen in der Dokumentation finden. Könnten Sie eine Referenz hinzufügen?
Alex

4
Für diejenigen, die keine Kurzschriftoptionen mögen, -eist --edit.
Kolyunya

2
@ Alex Die von theFreedomBanana hinzugefügten Referenzzitate stammen aus dem Abschnitt BEARBEITEN VON PATCHES ingit --help add
Randall

8
Dies ist die einzige Antwort (die nur Git erfordert), die das Problem des zeilenweisen Hinzufügens / Entfernens löst, wenn Sie sim interaktiven Patch-Modus keine Hunks verkleinern können.
cdosborn

3
Es kann hilfreich sein zu verstehen, dass dieser Befehl ( git add -e) den Dateiinhalt auf der Festplatte * nicht * ändert. Es wird nur ein Teil der Änderungen von nicht inszeniert nach inszeniert (Index) verschoben.
Penghe Geng

44

Wenn Sie vim verwenden, können Sie das hervorragende Plugin namens fugitive ausprobieren .

Sie können den Unterschied einer Datei zwischen Arbeitskopie und Index mit :Gdiffanzeigen und dann dem Index Zeilen oder Hunks hinzufügen, indem Sie klassische vim diff-Befehle wie verwenden dp. Speichern Sie die Änderungen im Index und legen Sie fest :Gcommit, und Sie sind fertig.

Sehr gute einführende Screencasts hier (siehe insbesondere Teil 2 ).


Vielen Dank für diese Links. Genau das gleiche was ich brauche. Besonders :diffget/:diffputim visuellen Modus, wo ich bestimmte Zeilen auswählen kann, die ich zurücksetzen / festschreiben möchte. Stellen Sie also noch einmal sicher: vim ist großartig.
Goodniceweb

30

Ich würde dringend empfehlen, SourceTree von Atlassian zu verwenden. (Es ist kostenlos.) Es macht dies trivial. Sie können einzelne Codeblöcke oder einzelne Codezeilen schnell und einfach bereitstellen.

Geben Sie hier die Bildbeschreibung ein


1
Ich bin damit einverstanden, dass SourceTree ein gutes Werkzeug für diesen Zweck ist, da es Ihnen eine feinkörnigere Kontrolle bietet, als dies über die Befehlszeile möglich ist.

19
@cupcake Ich würde das Gegenteil argumentieren, da SourceTree wahrscheinlich diese ausführbaren Befehlszeilen-Git-Dateien verwendet. Inhärent wird es immer möglich sein, dieselben (oder mehr) feinkörnigen Aktionen über die "Befehlszeile" auszuführen.
TutuDajuju

2
Ungeachtet des feinkörnigen Arguments würde ich SourceTree wärmstens empfehlen, da die Bereitstellung von Hunks und einzelnen Zeilen sehr einfach ist: i.imgur.com/85bNu4C.png
Mars Robertson

1
@tutuDajuju In diesem Fall bin ich mir nicht sicher, ob das stimmt. SourceTree kann auswählen, welche Teile Zeile für Zeile inszeniert werden sollen . Sie müssen nicht ein ganzes Stück inszenieren; Sie können 2 Zeilen in der Mitte eines Stücks inszenieren. Ich habe jedoch keine Ahnung, wie das erreicht wird. (Im Moment versuche ich, die Unfähigkeit von SourceTree zu umgehen, bestimmte Zeilen für eine nicht verfolgte Datei bereitzustellen. Ich bin hier gelandet und habe nach einer Problemumgehung gesucht, nur um festzustellen, dass Git anscheinend nicht die Fähigkeit bietet, Zeile für Zeile zu arbeiten überhaupt nicht. Zumindest nicht auf einfache Weise.)
jpmc26

1
@Sun können Sie auf Zeile 50 klicken und die Umschalttaste drücken + auf Zeile 100 klicken und dann inszenieren. Sie können Linie 50-100 in Sourcetree leicht inszenieren :)
Ryan123

26

Beachten Sie, dass Sie zur Verwendung git add --patchfür eine neue Datei zuerst die Datei zum Index hinzufügen müssen mit git add --intent-to-add:

git add -N file
git add -p file

23

Wenn ich viele Änderungen vorgenommen habe und am Ende einige Commits aus den Änderungen erstellen werde, möchte ich meinen Startpunkt vorübergehend speichern, bevor ich Dinge bereitstelle.

So was:

$ git stash -u
Saved working directory and index state WIP on master: 47a1413 ...
$ git checkout -p stash
... step through patch hunks
$ git commit -m "message for 1st commit"
$ git checkout -p stash
... step through patch hunks
$ git commit -m "message for 2nd commit"
$ git stash pop

Whymarrhs ​​Antwort ist das, was ich normalerweise mache, außer manchmal gibt es viele Änderungen und ich kann sagen, dass ich beim Inszenieren von Dingen einen Fehler machen könnte, und ich möchte einen festen Zustand, auf den ich für einen zweiten Durchgang zurückgreifen kann.


12

Wenn Sie Emacs verwenden, schauen Sie sich Magit an , das eine Git-Oberfläche für Emacs bietet. Es unterstützt das Staging von Hunks (Teilen von Dateien) recht gut.


Ich stolpere oft über einen Git-Befehl, der einen Editor öffnen möchte, wenn ich ihn über ein Mx-Shell-Fenster ausgeführt habe. Fängt Magit diese Verrücktheit ab und öffnet dafür nur einen neuen Puffer? (bitte keine Hintergrund-Emacs-Daemon-Hinweise; trotzdem danke, aber das Leben ist zu kurz).
user2066657

Nein, soweit ich das beurteilen kann, fängt es das nicht ab. Aber nehmen Sie nicht einfach mein Wort dafür, denn (1) ich benutze das Shell-Fenster in Emacs kaum und (2) ich benutze normalerweise emacsclient. Having said that, wenn emacsclient ist eine Option für Sie, dass zumindest ein zusätzliches Fenster mit Emacs verhindert wird geöffnet und der „COMMIT_EDITMSG“ Puffer wurde in meinen vorhandenen Emacs - Fenstern geöffnet.
Mark van Lent


9

Für diejenigen, die Git Extensions verwenden :

Wählen Sie im Fenster "Festschreiben" die Datei aus, die Sie teilweise festschreiben möchten, wählen Sie dann im rechten Bereich den Text aus, den Sie festschreiben möchten, klicken Sie mit der rechten Maustaste auf die Auswahl und wählen Sie im Kontextmenü die Option "Ausgewählte Zeilen inszenieren".


2
Die Tastenkombination in Git-Erweiterungen für "Ausgewählte Zeilen sinszenieren " ist sehr nützlich, um schnell Teile von Dateien für ein Commit bereitzustellen.
Alchemistmatt

8

Ähnlich wie bei der Antwort von jdsumsion können Sie auch Ihre aktuelle Arbeit speichern, aber dann ein Difftool wie meld verwenden, um ausgewählte Änderungen aus dem Speicher zu ziehen. Auf diese Weise können Sie die Hunks sogar sehr einfach manuell bearbeiten, was ein bisschen schmerzhaft ist, wenn Sie git add -p:

$ git stash -u
$ git difftool -d -t meld stash
$ git commit -a -m "some message"
$ git stash pop

Mit der Stash-Methode können Sie testen, ob Ihr Code noch funktioniert, bevor Sie ihn festschreiben.


Das funktioniert gut, aber wenn Sie es verwenden git commit --amend, scheint es, dass Sie den Stash danach nicht mehr öffnen können, oder gibt es eine Möglichkeit, dies zu tun?
Mark

7

Wenn Sie eine vorherige Antwort hinzufügen und die Befehlszeile bevorzugen, können Sie bei der Eingabe git add -e myfilezeilenweise auswählen, was Sie festschreiben möchten, da dieser Befehl einen Editor mit den folgenden Unterschieden öffnet:

Geben Sie hier die Bildbeschreibung ein

Wie Sie vielleicht +wissen, sind Zeilen, die mit beginnen, Hinzufügungen, Zeilen, die mit beginnen, -Löschungen. Damit:

  • Um einen Zusatz nicht zu inszenieren, löschen Sie einfach diese Zeile.
  • Um eine Löschung nicht durchzuführen, ersetzen Sie sie einfach durch -Leerzeichen .

Folgendes git add -hsagt das Hinzufügen von Dateien auf diese Weise aus (Patchen von Dateien):

hinzugefügter Inhalt Der hinzugefügte Inhalt wird durch Zeilen dargestellt, die mit "+" beginnen. Sie können das Bereitstellen von Hinzufügungszeilen verhindern, indem Sie sie löschen.

entfernter Inhalt: Entfernter Inhalt wird durch Zeilen dargestellt, die mit "-" beginnen. Sie können das Staging ihrer Entfernung verhindern, indem Sie das "-" in ein "" (Leerzeichen) konvertieren.

Geänderter Inhalt: Geänderter Inhalt wird durch "-" Zeilen (Entfernen des alten Inhalts) gefolgt von "+" Zeilen (Hinzufügen des Ersatzinhalts) dargestellt. Sie können das Staging der Änderung verhindern, indem Sie "-" Zeilen in "" konvertieren und "+" Zeilen entfernen. Beachten Sie, dass das Ändern nur der Hälfte des Paares zu verwirrenden Änderungen des Index führen kann.

Achtung: Ändern Sie nicht den Inhalt der Datei, dies ist kein guter Ort, um dies zu tun. Ändern Sie einfach die Operatoren für gelöschte oder hinzugefügte Zeilen.


Welche vorherige Antwort? Die Antworten werden basierend auf der Anzahl der Punkte gespeichert. Ihre Antwort befindet sich jetzt an einer anderen Stelle als zu dem Zeitpunkt, als Sie sie geschrieben haben, im Vergleich zu anderen Antworten.
KulaGGin

Ich glaube, die Antwort, auf die verwiesen wird, stammt von @theFreedomBanana
K. Symbol

6

Das vim-gitgutter- Plugin kann Hunks inszenieren, ohne den vim-Editor zu verlassen

:GitGutterStageHunk

Daneben bietet es andere coole Funktionen wie eine Diff-Sign-Spalte wie in einigen modernen IDEs

Wenn nur ein Teil des Stücks vim-flüchtig inszeniert werden soll

:Gdiff

Ermöglicht dann die Auswahl des Sichtbereichs :'<,'>diffputoder :'<,'>diffgetdas Stufen / Zurücksetzen einzelner Linienänderungen.



4

Mit TortoiseGit:

Klicken Sie mit der rechten Maustaste auf die Datei und verwenden Sie Context Menu → Restore after commit. Dadurch wird eine Kopie der Datei erstellt, wie sie ist. Anschließend können Sie die Datei bearbeiten, z. B. in TortoiseGitMerge, und alle Änderungen rückgängig machen, die Sie nicht festschreiben möchten. Nach dem Speichern dieser Änderungen können Sie die Datei festschreiben.


4

Es ist 10 Jahre her, seit diese Frage gestellt wurde. Und ich hoffe, diese Antwort wird jemandem nützlich sein. Wie in der Antwort hier erwähnt , wo GUI keine Option ist, hilft Andrew Shaduras crecord-Erweiterung dabei , ein ncurses-Fenster zu öffnen , in dem wir die zu festschreibenden Zeilen auswählen können.

Richten Sie die Erweiterung wie folgt ein:

git clone https://github.com/andrewshadura/git-crecord
cd git-crecord
./setup.py install
ln -s $PWD/git-crecord ~/.local/bin/git-crecord

cd zu deinem git repo und rufe es wie folgt auf:

git crecord

Dies würde die ncurses-Schnittstelle aufrufen, die wie unten gezeigt verwendet werden kann. Durch Drücken der folgenden Tasten im Fenster ncurses werden bestimmte Aktionen ausgeführt:

f       hunk toggle fold (arrow keys can also be used)
space   toggle hunk selection
a       toggle commit or amend
c       confirm and open commit window

Screencast mit einer BeispielnutzungBeispiel


3

Für Atom- Benutzer enthält das Paket github interaktives Staging im Stil von git gui. Verknüpfungen finden Sie in der Dokumentation des Pakets .

Mit Atom können Sie mit einem Thema arbeiten, das einen dunklen Hintergrund hat (standardmäßig git guieinen weißen Hintergrund).



2

git-meld-index - Zitat aus der Website:

git-meld-index führt meld - oder ein anderes Git-Difftool (kdiff3, diffuse usw.) - aus, damit Sie Änderungen am Git-Index (auch als Git-Staging-Bereich bezeichnet) interaktiv inszenieren können.

Dies ähnelt der Funktionalität von git add -p und git add --interactive. In einigen Fällen ist meld einfacher / schneller zu verwenden als git add -p. Das liegt daran, dass Sie mit meld beispielsweise Folgendes tun können:

  • mehr Kontext sehen
  • siehe Intra-Line-Unterschiede
  • von Hand bearbeiten und 'Live'-Diff-Updates sehen (aktualisiert nach jedem Tastendruck)
  • Navigieren Sie zu einer Änderung, ohne zu jeder Änderung, die Sie überspringen möchten, 'n' zu sagen

Verwendungszweck

Führen Sie in einem Git-Repository Folgendes aus:

git meld-index

Sie sehen meld (oder Ihr konfiguriertes Git-Difftool) mit:

LEFT : temporäre Verzeichnis contining Dateien von Ihrem Arbeits Baum kopiert

RECHTS : Temporäres Verzeichnis mit dem Inhalt des Index. Dies schließt auch Dateien ein, die noch nicht im Index enthalten sind, aber in der Arbeitskopie geändert oder nicht verfolgt werden. In diesem Fall wird der Dateiinhalt von HEAD angezeigt.

Bearbeiten Sie den Index (rechte Seite), bis Sie zufrieden sind. Denken Sie daran, bei Bedarf zu speichern.

Wenn Sie fertig sind, schließen Sie meld und git-meld-index aktualisiert den Index so, dass er mit dem Inhalt des temporären Verzeichnisses auf der rechten Seite von meld übereinstimmt, das Sie gerade bearbeitet haben.


2

Wenn es auf der WindowsPlattform ist, ist meiner Meinung git guinach ein sehr gutes Werkzeug für stage/ commitwenige Zeilen aus der unstagedDatei

1. Hunk weise:

  • Wählen Sie die Datei aus dem unstagged ChangesAbschnitt
  • Klicken Sie mit der rechten Maustaste auf einen Codeabschnitt, der bereitgestellt werden muss
  • Wählen Stage Hunk for commit

2. Linie weise:

  • Wählen Sie die Datei aus dem unstagged ChangesAbschnitt
  • Wählen Sie die Linie / Linien aus, die inszeniert werden sollen
  • Klicken Sie mit der rechten Maustaste und wählen Sie Stage Lines for commit

3. Wenn Sie die gesamte Datei mit Ausnahme einiger Zeilen bereitstellen möchten:

  • Wählen Sie die Datei aus dem unstagged ChangesAbschnitt
  • Drücken Sie Ctrl+T (Stage file to commit)
  • Die ausgewählte Datei wird jetzt in Staged ChangesAbschnitt verschoben
  • Wählen Sie die Linie / Linien aus, die inszeniert werden sollen
  • Klicken Sie mit der rechten Maustaste und wählen Sie UnStage Lines for commit

1

Wie eine Antwort oben zeigt, können Sie verwenden git add --patch filename.txt

oder die Kurzform git add -p filename.txt

... aber für Dateien, die sich bereits in Ihrem Repository befinden, ist es in s viel besser, das Flag --patch direkt im Befehl commit zu verwenden (wenn Sie eine ausreichend aktuelle Version von git verwenden): git commit --patch filename.txt

... oder wieder die Kurzform git commit -p filename.txt

... und dann mit den genannten Schlüsseln (j / n usw.) Zeilen auswählen, die in das Commit aufgenommen werden sollen.


Was gibt Ihnen das " git add -p filename.txt" außer weniger Spielraum für Fehler? Wenn Sie die Änderung der Teildatei durcheinander bringen, ist das Rückgängigmachen eines Adds besser als das Rückgängigmachen eines Commits.
CTMacUser

Ich weiß nicht warum, aber wenn ich 'n' sage, wird die Zeile eingeschlossen ... und wenn ich auf dem 2. Stück 'y' sage, wird sie auch eingeschlossen.
Chovy

1

git-cola ist eine großartige GUI und hat auch diese Funktion eingebaut. Wählen Sie einfach die zu inszenierenden Zeilen aus und drücken Sie S. Wenn keine Auswahl getroffen wird, wird das gesamte Stück bereitgestellt.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.