772 Stimmen

Wie kann man alle Git-Commits zu einem zusammenfassen?

Wie drückst du dein gesamtes Repository auf den ersten Commit zusammen?

Ich kann zum ersten Commit neu basieren, aber dann hätte ich 2 Commits. Gibt es eine Möglichkeit, auf den Commit vor dem ersten zu verweisen?

43 Stimmen

@innaM - Es ist der ursprüngliche Commit, der den Git hervorgebracht hat. (Hofft, dass der Humor gut genug durch das Internet übertragen wird).

14 Stimmen

Für diejenigen, die später zu dieser Frage kommen, achten Sie darauf, die modernere Antwort zu verwenden.

1 Stimmen

Verwandt, aber kein Duplikat (--root ist tatsächlich nicht die beste Lösung zum Zusammenfassen aller Commits, wenn es viele davon gibt, die zusammengefasst werden müssen): Kombinieren der ersten beiden Commits eines Git-Repositorys?.

989voto

Jordan Lewis Punkte 15714

Ab git 1.6.2 können Sie git rebase --root -i verwenden.

Ändern Sie für jeden Commit außer dem ersten pick in squash im Editor, der erscheint.

3 Stimmen

89 Stimmen

Diese Antwort ist ok, aber wenn Sie interaktiv mehr als, sagen wir, 20 Commits neu basieren, wird das interaktive Rebasieren wahrscheinlich viel zu langsam und unhandlich sein. Sie dürften Schwierigkeiten haben, Hunderte oder Tausende von Commits zu squaschen. In diesem Fall würde ich einen soft oder mixed Reset zum Root-Commit durchführen und dann erneut committen.

0 Stimmen

Dies war der einzige Weg, wie ich einen Master-Zweig zu meinem neu erstellten GitHub-Repository hinzufügen konnte, nachdem ich einen Feature-Zweig gepusht hatte, für den ich einen Pull-Request erstellen wollte.

558voto

ryenus Punkte 13738

Einzeiler (für Bash/Zsh)

Sie können einen squash-all commit direkt von HEAD aus erstellen, ohne jegliches Rebase, führen Sie einfach aus:

git reset $(git commit-tree HEAD^{tree} -m "Ein neuer Anfang")

Hinweis: Dies erfordert eine POSIX-kompatible Shell wie bash/zsh oder Git Bash unter Windows.

Erstellen einer Alias in ~/.gitconfig

[alias]
  squash-all = "!f(){ git reset $(git commit-tree HEAD^{tree} \"$@\");};f"

Dann führen Sie einfach aus: git squash-all -m "ein ganz neuer Anfang"

Hinweis: Geben Sie entweder die Commit-Nachricht über standardmäßige Eingabe oder über die Optionen -m/-F an, genau wie beim git commit Befehl. Siehe git-commit-tree Anleitung.

Alternativ können Sie das Alias mit dem folgenden Befehl erstellen:

git config --global alias.squash-all '!f(){ git reset $(git commit-tree HEAD^{tree} "$@");};f'

Erklärung

  1. Erstellen eines einzelnen Commits über git commit-tree

    Was git commit-tree HEAD^{tree} -m "Ein neuer Anfang" macht ist:

    Erstellt ein neues Commit-Objekt auf Basis des bereitgestellten Tree-Objekts und gibt die ID des neuen Commits auf der Standardausgabe aus. Die Protokollnachricht wird von der Standardmäßigen Eingabe gelesen, es sei denn, die Optionen -m oder -F werden angegeben.

    Der Ausdruck HEAD^{tree} repräsentiert das Tree-Objekt, das zu HEAD gehört, nämlich die Spitze Ihres aktuellen Branches. Siehe Tree-Objekte und Commit-Objekte.

  2. Zurücksetzen des aktuellen Branches auf das neue Commit

    Dann setzt git reset einfach den aktuellen Branch auf das neu erstellte Commit-Objekt zurück.

    Auf diese Weise wird nichts im Arbeitsbereich geändert, und es ist kein Rebase/Squash erforderlich, was es wirklich schnell macht. Und die benötigte Zeit ist unabhängig von der Repositorygröße oder der Geschichte.


Variante: Neues Repository aus einer Projektvorlage

Dies ist nützlich, um den "initial commit" in einem neuen Projekt mithilfe eines anderen Repositories als Vorlage/Archetyp/Saat/Gerüst zu erstellen. Zum Beispiel:

cd mein-neues-projekt
git init
git fetch --depth=1 -n https://github.com/toolbear/panda.git
git reset --hard $(git commit-tree FETCH_HEAD^{tree} -m "Initialer Commit")

Dies umgeht das Hinzufügen des Vorlagen-Repositorys als Remote (origin oder anders) und kollabiert die Geschichte des Vorlagen-Repositorys in Ihren initialen Commit.

8 Stimmen

Die Git-Revisions-Syntax (HEAD^{tree}) Syntax wird hier erklärt, falls sich jemand anderes gefragt hat: jk.gs/gitrevisions.html

0 Stimmen

@ColinBowern, danke für den Hinweis, ich habe die Antwort mit etwas Informationen zur Baumobjektsyntax aktualisiert und einen Verweis aus dem Git-Buch hinzugefügt.

2 Stimmen

Wird dadurch sowohl das lokale als auch das entfernte Repository zurückgesetzt oder nur eines von beiden?

299voto

Wenn Sie alle Ihre Commits nur bis zum Stammcommit zusammenführen möchten, dann während

git rebase --interaktiv --root

funktionieren kann, ist es für eine große Anzahl von Commits (zum Beispiel Hunderte von Commits) unpraktisch, weil die Rebase-Operation wahrscheinlich sehr langsam ausgeführt wird, um die interaktive Rebase-Editor-Commit-Liste zu generieren und den Rebase selbst auszuführen.

Hier sind zwei schnellere und effizientere Lösungen, wenn Sie eine große Anzahl von Commits zusammenführen:

Alternative Lösung #1: Waisen-Branches

Sie können einfach einen neuen Waisen-Branch an der Spitze (d.h. dem neuesten Commit) Ihres aktuellen Branches erstellen. Dieser Waisen-Branch bildet den initialen Stammcommit eines völlig neuen und separaten Commit-Verlaufbaums, der effektiv äquivalent zur Zusammenführung aller Ihrer Commits ist:

git checkout --orphan neuer-master master
git commit -m "Geben Sie die Commit-Nachricht für Ihren neuen initialen Commit ein"

# Überschreiben Sie den alten Master-Branch-Verweis mit dem neuen
git branch -M neuer-master master

Dokumentation:

Alternative Lösung #2: Soft Reset

Eine weitere effiziente Lösung besteht darin, einfach einen gemischten oder soft reset auf den Stammcommit zu verwenden:

git branch vorReset

git reset --soft 
git commit --amend

# Überprüfen Sie, dass der neue bearbeitete Stamm nicht vom vorherigen Branch-Zustand abweicht
git diff vorReset

Dokumentation:

54 Stimmen

Alternative Lösung #1: Waisenäste - toll!

14 Stimmen

Alternative Lösung #1 FTW. Nur um es hinzuzufügen, wenn Sie Ihre Änderungen auf den Remote pushen möchten, tun Sie git push origin master --force.

3 Stimmen

Sollte nicht vergessen git push --force

170voto

Pat Notz Punkte 196406

Vielleicht ist der einfachste Weg, einfach ein neues Repository mit dem aktuellen Stand der Arbeitskopie zu erstellen. Wenn Sie alle Commit-Messages behalten möchten, könnten Sie zuerst git log > original.log ausführen und dann diese für Ihre initiale Commit-Nachricht im neuen Repository editieren:

rm -rf .git
git init
git add .
git commit

oder

git log > original.log
# editiere original.log wie gewünscht
rm -rf .git
git init
git add .
git commit -F original.log

78 Stimmen

Aber Sie verlieren Äste mit dieser Methode

0 Stimmen

@OlivierRefalo - Es gibt keine Möglichkeit, Zweige zu bewahren, während die gesamte Historie auf einen einzigen Commit reduziert wird (einen neuen initialen Commit erstellen). Wenn jemand Zweige erhalten möchte, muss er den alten initialen Commit aufbewahren. Um das zu tun, rebase gegen den initialen Commit (wie in der Frage beschrieben) und behalten Sie möglicherweise bis zu zwei Commits.

0 Stimmen

Eigentlich gibt es einen Weg, um Zweige zu erhalten, siehe Antwort von @FrefichRaabe. Allerdings klingt das Konzept alter Zweige mit einer Geschichte, die auf einen einzigen Commit reduziert wurde, seltsam.

97voto

kusma Punkte 6278
echo "Nachricht" | git commit-tree HEAD^{tree}

Dies erstellt einen verwaisten Commit mit dem Baum von HEAD und gibt dessen Namen (SHA-1) auf stdout aus. Setzen Sie dann einfach Ihren Branch dort zurück.

git reset SHA-1

Um das obige in einem Schritt auszuführen:

git reset $(git commit-tree HEAD^{tree} -m "Erster Commit.")

41 Stimmen

git reset $(git commit-tree HEAD^{tree} -m "commit message") würde es einfacher machen.

7 Stimmen

^ DAS! - sollte eine Antwort sein. Nicht ganz sicher, ob es die Absicht des Autors war, aber es war meine (benötigt ein sauberes Repository mit nur einem Commit, und das erledigt den Job).

0 Stimmen

@ryenus, deine Lösung hat genau das getan, wonach ich gesucht habe. Wenn du deinen Kommentar als Antwort hinzufügst, werde ich ihn akzeptieren.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X