2014-12-29 12 views
11

während ich an neuem Code arbeite, mache ich viele kleine Commits, um meine Änderungen zu verfolgen. Meine Firma bevorzugt jedoch, dass jede Funktion in einem einzigen Commit festgelegt wird. Die Lösung besteht also darin, meinen gesamten Zweig auf einen einzigen Commit zu reduzieren.Git - Squash ganzer Zweig - eine Linie Squash Befehl

Wie komprimiere ich einen ganzen Zweig, ohne git rebase --interactive zu verwenden und dann zu squash für alle commits zu ändern?

+4

Vielleicht verwenden Sie 'git merge --squash', um zu vermeiden, dass Sie Ihren gesamten Zweig vorher quetschen müssen? – twalberg

+0

@twalberg bitte machen Sie eine Antwort – jthill

+1

'git Merge --squash' funktioniert nicht, wenn Sie Github Pull-Anfragen zu tun, die meisten Ihrer Branche Merging, die eine ziemlich häufige Fall ist – meagar

Antwort

1

Bearbeiten Sie Ihre git Konfigurationsdatei ~/.gitconfig und folgendes Alias ​​Abschnitt hinzufügen

[alias] 
    squash = "!f(){ CUR=`git rev-parse HEAD` && git reset --soft ${1} && git commit -m \"$(git log --format=%B ${1}..${CUR})\"; };f" 

Dieser Alias ​​der aktuellen HEAD Hash begehen wird, auf die setzt zurück verpflichten Sie angeben, und erstellt ein neues verpflichten alle zu erhalten die Commit-Nachrichten.

Verbrauch:

git squash <refspec> 

Refspec jeder gültige Referenz begehen wie ein Commit Hash, Zweignamen, Tag-Name, HEAD^HEAD~3

2

findet nur den Hash für das Commit sein können, bevor SieFormal den Zweig begonnen und kopiere es in die Zwischenablage. Führen Sie dann einen Reset auf diesen Hash durch.

$ git reset [hash] 

Dann einfach neu hinzufügen und erneut die Änderungen in einer einzigen Nachricht festschreiben.

$ git add -A 
$ git commit -m 'EVERYTHING SQUASHED' 
+1

Wenn Sie einen Soft-Reset durchführen wollen, müssen Sie explizit das '--soft' Flag (' git reset --soft ') verwenden, weil Git führt standardmäßig einen gemischten Reset durch. – Jubobs

+0

Jut ein Standard-Mixed-Reset erreicht das gewünschte Squashing. – onlythefinestwilldo

+3

Ja, aber Sie schreiben: * Machen Sie einen Soft-Reset auf diesen Hash *; das ist irreführend. – Jubobs

11

Meine bevorzugte Methode ist ein Zweiliner (mit Ausnahme der Schritte 1 und 4 unten). Die Vorteile sind, dass Sie keine Commit-IDs kennen/notieren müssen, Sie können einen einfachen Alias ​​schreiben, um alle erforderlichen Schritte auszuführen und Ihren gesamten Zweig auf Ursprung/Master zu verschieben, so dass die tatsächliche Zusammenführung in Master sein kann ein Schnellvorlauf und es kann keine Konflikte geben.

Zuerst meine Annahmen:

  • Sie auf einem Zweig arbeitet namens my-feature-branch. Dieser Zweig ist von master durch mehrere Commits divergiert; Dies ist der ausgecheckte Zweig.
  • Ihre lokale master Spuren entfernten Zweig origin/master
  • Sie wollen von my-feature-branch in einem einzigen, alle Ihre Commits ontop den aktuellen Stand der origin/master verpflichten zerquetschen (nicht Ihre lokale master, die veraltet sein können)
  • Alle Ihre Änderungen verpflichtet sind, haben Sie keine Änderungen unstaged (sie werden während git reset --hard)

Mein Prozess ist wie folgt verloren:

  1. holen, so origin/master ist Strom:

    $ git fetch 
    
  2. durch alle Commits auf dem lokalen Zweig Wegwerfen es Zurücksetzen auf origin/master

    $ git reset --mixed origin/master 
    
  3. Merge alle Ihre alten Änderungen Punkt aus dem vorherigen Zustand Ihrer Filiale in den Index

    $ git merge --squash [email protected]{1} 
    
  4. Änderungen Commit - Git wird Ihr Editor mit einer Commit-Nachricht vorab füllen Sie alle Nachrichten aus dem zerquetscht begehen enthält verpflichtet

Die einfache alias ich erwähnt wäre:

alias squash="git fetch; git reset --mixed origin/master; git merge --squash [email protected]{1}" 
4

Wahrscheinlich Die beste Option hierfür wäre die Verwendung von git merge --squash zur Zusammenführungszeit. Das wird Ihre Branche so belassen, wie sie sich entwickelt hat, was oft viel einfacher zu beheben ist, weil Sie die Vorstellung haben "Ich habe diese spezifische Funktionalität in Commit Z geändert", und wenn Sie sich diese spezifische Aufgabe ansehen, haben Sie alle Der Kontext von Änderungen, die Sie an mehreren Dateien vorgenommen haben - ein einzelner Commit zu betrachten, bei dem es sich um die gequetschten Ergebnisse Ihres Entwicklungspfades handelt, macht es etwas schwieriger, sich daran zu erinnern. "Oh, ja, ich musste diese eine Sache in einer anderen Datei ändern , auch...". Sie haben auch den Vorteil, git bisect zu verwenden, wenn Sie Ihren gesamten Weg zur Verfügung haben - alles, was es Ihnen im gequetschten Fall sagen könnte, ist "dieses riesige Festschreiben brach hier etwas".

Das Ergebnis der Verwendung von git merge --squash ist ein einzelner Commit für den Zweig, in den Sie "einbinden", der die kumulativen Änderungen von Ihrem Zweig enthält, aber Ihren ursprünglichen Zweig allein belässt.

0

Ich glaube nicht, dass dies die richtige Antwort für diese Frage ist.

Aber ich Squash in der Regel meinen Zweiges vor dem Pull-Request an den Remote-Upstream-Master machen Sie den folgenden Befehl:

git rebase -i master 

Aber Sie müssen dann immer noch entscheiden, welche und Squash zu holen.

Verwandte Themen