-
1. Erste Schritte
-
2. Git Grundlagen
-
3. Git Branching
- 3.1 Branches auf einen Blick
- 3.2 Einfaches Branching und Merging
- 3.3 Branch-Management
- 3.4 Branching-Workflows
- 3.5 Remote-Branches
- 3.6 Rebasing
- 3.7 Zusammenfassung
-
4. Git auf dem Server
- 4.1 Die Protokolle
- 4.2 Git auf einem Server einrichten
- 4.3 Erstellung eines SSH-Public-Keys
- 4.4 Einrichten des Servers
- 4.5 Git-Daemon
- 4.6 Smart HTTP
- 4.7 GitWeb
- 4.8 GitLab
- 4.9 Von Drittanbietern gehostete Optionen
- 4.10 Zusammenfassung
-
5. Verteiltes Git
-
6. GitHub
-
7. Git Tools
- 7.1 Revisions-Auswahl
- 7.2 Interaktives Stagen
- 7.3 Stashen und Bereinigen
- 7.4 Deine Arbeit signieren
- 7.5 Suchen
- 7.6 Den Verlauf umschreiben
- 7.7 Reset entzaubert
- 7.8 Fortgeschrittenes Merging
- 7.9 Rerere
- 7.10 Debuggen mit Git
- 7.11 Submodule
- 7.12 Bundling
- 7.13 Replace (Ersetzen)
- 7.14 Anmeldeinformationen speichern
- 7.15 Zusammenfassung
-
8. Git einrichten
- 8.1 Git Konfiguration
- 8.2 Git-Attribute
- 8.3 Git Hooks
- 8.4 Beispiel für Git-forcierte Regeln
- 8.5 Zusammenfassung
-
9. Git und andere VCS-Systeme
- 9.1 Git als Client
- 9.2 Migration zu Git
- 9.3 Zusammenfassung
-
10. Git Interna
-
A1. Anhang A: Git in anderen Umgebungen
- A1.1 Grafische Schnittstellen
- A1.2 Git in Visual Studio
- A1.3 Git in Visual Studio Code
- A1.4 Git in IntelliJ / PyCharm / WebStorm / PhpStorm / RubyMine
- A1.5 Git in Sublime Text
- A1.6 Git in Bash
- A1.7 Git in Zsh
- A1.8 Git in PowerShell
- A1.9 Zusammenfassung
-
A2. Anhang B: Git in deine Anwendungen einbetten
- A2.1 Die Git-Kommandozeile
- A2.2 Libgit2
- A2.3 JGit
- A2.4 go-git
- A2.5 Dulwich
-
A3. Anhang C: Git Kommandos
- A3.1 Setup und Konfiguration
- A3.2 Projekte importieren und erstellen
- A3.3 Einfache Snapshot-Funktionen
- A3.4 Branching und Merging
- A3.5 Projekte gemeinsam nutzen und aktualisieren
- A3.6 Kontrollieren und Vergleichen
- A3.7 Debugging
- A3.8 Patchen bzw. Fehlerkorrektur
- A3.9 E-mails
- A3.10 Externe Systeme
- A3.11 Administration
- A3.12 Basisbefehle
7.3 Git Tools - Stashen und Bereinigen
Stashen und Bereinigen
Es passiert manchmal, dass dein Projekt nach einer Bearbeitung in einem unordentlichen Zustand. Stelle dir vor du willst in einen anderen Branch wechseln, um an etwas anderem zu arbeiten.
Das Problem ist, dass du keinen Commit mit halbfertiger Arbeit machen willst, nur um später an diesen Punkt zurückkehren zu können.
Die Antwort auf dieses Problem ist der Befehl git stash
.
Stashing nimmt den unsauberen Zustand deines Arbeitsverzeichnisses – das heißt, deine geänderten, getrackten Dateien und gestagte Änderungen – und speichert ihn in einem Stapel unvollendeter Änderungen, die du jederzeit (auch auf einen anderen Branch) wieder anwenden kannst.
Anmerkung
|
Migrieren zu
git stash push
Ende Oktober 2017 gab es eine ausführliche Diskussion innerhalb der Git-Mailingliste, bei der der Befehl
|
Deine Arbeit stashen
Um das Stashen zu demonstrieren, gehe in dein Projekt und beginne mit der Arbeit an ein paar Dateien. Du kannst dann eine der Änderungen der Staging-Area hinzufügen.
Wenn du git status
ausführst, kannst du den aktuellen Status sehen:
$ git status
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: index.html
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: lib/simplegit.rb
Du möchtest nun den Branch wechseln, aber du willst das bisherige noch nicht committen, also solltest du die Änderungen stashen.
Um einen neuen Stash zu erstellen, führe git stash
oder git stash push
aus:
$ git stash
Saved working directory and index state \
"WIP on master: 049d078 Create index file"
HEAD is now at 049d078 Create index file
(To restore them type "git stash apply")
Anschliessend siehst du, dass dein Arbeitsverzeichnis bereinigt ist:
$ git status
# On branch master
nothing to commit, working directory clean
An dieser Stelle kannst du die Branches wechseln und anderswo arbeiten. Deine Änderungen werden solange gespeichert.
Um zu sehen, welche Stashes du gespeichert hast, kannst du git stash list
verwenden:
$ git stash list
stash@{0}: WIP on master: 049d078 Create index file
stash@{1}: WIP on master: c264051 Revert "Add file_size"
stash@{2}: WIP on master: 21d80a5 Add number to log
Hier wurden vorher schon zwei Stashes gespeichert, so dass du Zugriff auf drei verschiedene gestashte Arbeiten hast.
Du kannst den soeben versteckten Stash erneut aufrufen, indem du den Befehl verwendest, der in der Hilfe-Anzeige des ursprünglichen Stash-Befehls angezeigt wird: git stash apply
.
Wenn du einen der früheren Stashes anwenden möchtest, kannst du ihn durch einen Namen angeben, etwa so: git stash apply stash@{2}
.
Wenn du keinen Stash angibst, nimmt Git den neuesten Stash und versucht, ihn zu übernehmen:
$ git stash apply
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: index.html
modified: lib/simplegit.rb
no changes added to commit (use "git add" and/or "git commit -a")
Du kannst sehen, dass Git die Dateien, die du beim Speichern des Stashes zurückgesetzt hast, erneut modifiziert. In diesem Fall hattest du ein sauberes Arbeitsverzeichnis, als du versucht hast, den Stash anzuwenden den du auf den gleichen Branch anwenden wolltest, aus dem du ihn erzeugt hast. Ein sauberes Arbeitsverzeichnis und dessen Anwendung auf denselben Branch sind nicht nötig, um einen Stash erfolgreich anzulegen. Du kannst einen Stash in einem Branch speichern, später in einen anderen Branch wechseln und erneut versuchen, die Änderungen zu übernehmen. Du kannst auch geänderte und nicht übertragene Dateien in deinem Arbeitsverzeichnis haben, wenn du einen Stash anwendest. Git meldet dir Merge-Konflikte, wenn etwas nicht mehr sauber funktioniert.
Die Änderungen an deinen Dateien wurden erneut angewendet, aber die Datei, die du zuvor bereitgestellt hast, wurde nicht neu eingestellt.
Um das zu erreichen, musst du den Befehl git stash apply
mit der Option --index
ausführen und so dem Befehl anweisen, dass er versuchen soll, die gestagten Änderungen erneut anzuwenden.
Hättest du stattdessen diesen Befehl ausgeführt, wärst du an deine ursprüngliche Position zurückgekehrt:
$ git stash apply --index
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: index.html
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: lib/simplegit.rb
Die apply-Option versucht nur, die gestashte Arbeit zu übernehmen. Du hast sie weiterhin in deinem Stack.
Um sie zu entfernen, kann man git stash drop
mit dem Namen des zu entfernenden Stash ausführen:
$ git stash list
stash@{0}: WIP on master: 049d078 Create index file
stash@{1}: WIP on master: c264051 Revert "Add file_size"
stash@{2}: WIP on master: 21d80a5 Add number to log
$ git stash drop stash@{0}
Dropped stash@{0} (364e91f3f268f0900bc3ee613f9f733e82aaed43)
Man kann auch git stash pop
ausführen, um den Stash einzubringen und ihn dann sofort vom Stack zu entfernen.
Kreatives Stashing
Es gibt ein paar Stash-Varianten, die ebenfalls nützlich sein können.
Die erste, recht beliebte Option ist die --keep-index
Option zum git stash
Befehl.
Diese weist Git an, nicht nur alle bereitgestellten Inhalte in den zu erstellenden Stash aufzunehmen, sondern sie gleichzeitig im Index zu belassen.
$ git status -s
M index.html
M lib/simplegit.rb
$ git stash --keep-index
Saved working directory and index state WIP on master: 1b65b17 added the index file
HEAD is now at 1b65b17 added the index file
$ git status -s
M index.html
Eine weitere gebräuchliche Funktion von stash ist die Ablage der nicht getrackten sowie der getrackten Dateien.
Standardmäßig wird git stash
nur modifizierte und gestagte, getrackte Dateien aufnehmen.
Wenn du --include-untracked
oder -u
angeben, wird Git ungetrackte Dateien in den zu erstellenden Stash einschließen.
Trotzdem wird das Einfügen von nicht getrackten Dateien in den Stash weiterhin keine explizit zu ignorierenden Dateien enthalten, Um zusätzlich ignorierte Dateien einzubeziehen, verwende --all
(oder nur -a
).
$ git status -s
M index.html
M lib/simplegit.rb
?? new-file.txt
$ git stash -u
Saved working directory and index state WIP on master: 1b65b17 added the index file
HEAD is now at 1b65b17 added the index file
$ git status -s
$
Wenn du das --patch
Flag angibst, wird Git nicht alles, was modifiziert wurde, in den Stash aufnehmen, sondern dich fragen, welche der Änderungen du sicher verwahren willst und welche du noch in deinem Arbeitsverzeichnis behalten möchtest.
$ git stash --patch
diff --git a/lib/simplegit.rb b/lib/simplegit.rb
index 66d332e..8bb5674 100644
--- a/lib/simplegit.rb
+++ b/lib/simplegit.rb
@@ -16,6 +16,10 @@ class SimpleGit
return `#{git_cmd} 2>&1`.chomp
end
end
+
+ def show(treeish = 'master')
+ command("git show #{treeish}")
+ end
end
test
Stash this hunk [y,n,q,a,d,/,e,?]? y
Saved working directory and index state WIP on master: 1b65b17 added the index file
Einen Branch aus einem Stash erzeugen
Wenn Du etwas Arbeit stashen, sie eine Weile dort belassen und dann auf dem Branch weiter machen willst, aus dem du die Arbeit gestashet hast, könntest du ein Problem bekommen, die Änderungen wieder anzuwenden.
Wenn man versucht, eine Datei zu ändern, die man zwischenzeitlich schon bearbeitet hatte, erhält man einen Merge-Konflikt und muss versuchen, diesen aufzulösen.
Wenn du einen einfacheren Weg bevorzugst, um die gespeicherten Änderungen noch einmal zu testen, kannst du git stash branch <new branchname>
ausführen. Damit wird ein neuer Branch mit dem gewählten Branch-Namen erzeugt, der Commit, an der du gerade gearbeitet hast, auscheckt, deine Arbeit dort wieder eingesetzt und dann den Stash verworfen, wenn er erfolgreich angewendet wurde:
$ git stash branch testchanges
M index.html
M lib/simplegit.rb
Switched to a new branch 'testchanges'
On branch testchanges
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: index.html
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: lib/simplegit.rb
Dropped refs/stash@{0} (29d385a81d163dfd45a452a2ce816487a6b8b014)
Das ist ein interessanter Weg, mit dem man die gestashten Arbeiten leicht wiederherstellen und in einem neuen Branch bearbeiten kann.
Bereinigung des Arbeitsverzeichnisses
Letztendlich möchtest du vielleicht einige Arbeiten oder Dateien nicht in deinem Arbeitsverzeichnis ablegen, sondern sie einfach nur loswerden. Dafür ist der Befehl git clean
gedacht.
Einige gängige Beispiele, in denen du dein Arbeitsverzeichnis bereinigen musst, sind das Entfernen von überflüssigem Programmcode, der durch Merges oder externe Tools erzeugt wurde oder das Entfernen von Build-Artefakten, um einen sauberen Build zu ermöglichen.
Du solltest mit diesem Befehl sehr vorsichtig sein, da er darauf ausgelegt ist, Dateien aus deinem Arbeitsverzeichnis zu entfernen, die nicht getrackt werden.
Wenn du deine Absicht änderst, gibt es oft keine Möglichkeit mehr, den Inhalt dieser Dateien wiederherzustellen.
Eine bessere Option ist, git stash --all
auszuführen um alles zu entfernen, aber es in einem Stash zu speichern.
Angenommen, du willst unerwünschte Dateien entfernen oder dein Arbeitsverzeichnis bereinigen, dann könntest du das mit git clean
erledigen.
Um alle ungetrackten Dateien in deinem Arbeitsverzeichnis zu entfernen, kannst du git clean -f -d
ausführen, das alle Dateien entfernt, auch aus Unterverzeichnissen, die dadurch leer werden könnten.
Das -f bedeutet „force“ (dt. „erzwingen“ oder „unbedingt ausführen“) und wird benötigt, falls die Git-Konfigurationsvariable clean.requireForce
explizit nicht auf false gesetzt ist.
Wenn du wissen willst, was der Befehl bewirken könnte, dann führe ihn mit der Option --dry-run
(oder -n
) aus. Das bedeutet: „Mach einen Probelauf und berichte mir, was du gelöscht hättest“.
$ git clean -d -n
Would remove test.o
Would remove tmp/
Standardmäßig entfernt der Befehl git clean
nur die ungetrackten Dateien, die nicht ignoriert werden.
Jede Datei, die mit einem Suchmuster in deiner .gitignore
oder anderen Ignore-Dateien übereinstimmt, wird nicht entfernt.
Wenn du diese Dateien ebenfalls entfernen willst, z.B. um alle .o
Dateien zu entfernen, die von einem Build erzeugt wurden, kannst du dem clean-Befehl ein -x
hinzufügen.
$ git status -s
M lib/simplegit.rb
?? build.TMP
?? tmp/
$ git clean -n -d
Would remove build.TMP
Would remove tmp/
$ git clean -n -d -x
Would remove build.TMP
Would remove test.o
Would remove tmp/
Wenn du nicht weißt, was der git clean
Befehl bewirken wird, führe ihn immer mit einem -n
aus, um ihn zu überprüfen, bevor du das -n
in ein -f
änderst und ihn dann wirklich auszuführen.
Der andere Weg, wie du dich vorsehen kannst, ist den Prozess mit dem -i
oder „interactive“ Flag auszuführen.
Dadurch wird der Clean-Befehl im interaktiven Modus ausgeführt.
$ git clean -x -i
Would remove the following items:
build.TMP test.o
*** Commands ***
1: clean 2: filter by pattern 3: select by numbers 4: ask each 5: quit
6: help
What now>
Auf diese Weise kannst du jede Datei einzeln durchgehen oder interaktiv das zu entsprechende Lösch-Pattern festlegen.
Anmerkung
|
Es gibt eine ungewöhnliche Situation, in der man Git besonders energisch auffordern muss, das Arbeitsverzeichnis zu bereinigen.
Wenn du dich in einem Arbeitsverzeichnis befindest, unter dem du andere Git-Repositorys (vielleicht als Submodule) kopiert oder geklont hast, wird selbst |