it-swarm.com.de

Ist es möglich, bestimmte Commits beim Zusammenführen von Git auszuschließen?

Angenommen, ich möchte einen Release-Zweig mit dem Master-Zweig zusammenführen, und der Release-Zweig enthält einige Commits, die ich nicht in den Master-Zweig aufnehmen möchte. Gibt es eine Möglichkeit, die Zusammenführung durchzuführen, damit einer oder mehrere dieser Commits nicht zusammengeführt werden?

Meine bisherige Strategie ist Folgendes (im Master):

git merge --no-commit release-branch
# Resolve conflicts and apply reverse patch of the commits that I don't want included
git commit # Edit commit message so that it lists the commits that have been reverse-patched

Gibt es einen besseren Weg, dies zu tun?

65
Readonly

Erstellen Sie eine neue Verzweigung, setzen Sie die Verzweigung interaktiv neu auf, löschen Sie nicht gewünschte Commits und führen Sie diese zusammen.

Sie können keine Änderungen aus der Mitte eines Zweigs herausnehmen, ohne sie erneut aufzubereiten. Das Richtige passiert jedoch, wenn bei einer späteren Zusammenführung dieselben Änderungen festgestellt werden (z. B. durch Kirschpflücken und was nicht).

43
Dustin

Ich habe eine Lösung gefunden, die für mich funktioniert im Pro Git Buch .

Angenommen, Sie möchten die Datei config.php Ausschließen.

Auf Zweig A:

  1. Erstellen Sie eine Datei mit dem Namen .gitattributes In demselben Verzeichnis mit der folgenden Zeile: config.php merge=ours. Dies teilt git mit, welche Strategie beim Zusammenführen der Datei verwendet werden soll. In diesem Fall behält es immer Ihre Version, dh. Die Version in dem Zweig, in dem Sie zusammenführen.

  2. Fügen Sie die Datei .gitattributes Hinzu und bestätigen Sie

Auf Zweig B: Wiederholen Sie die Schritte 1-2

Versuchen Sie jetzt zu fusionieren. Ihre Datei sollte unangetastet bleiben.

107
fcurella

Wenn Sie einen Support-Zweig haben, in dem Sie Fehler beheben und neue Versionen erstellen. Auf master haben Sie die nächste Version, in der Sie auch häufig neue Versionen erstellen.

Jedes Mal, wenn Sie eine neue Version erstellen, ändern Sie die Version in einer Datei, schreiben Sie diese neue Datei fest, erstellen Sie ein Tag und drücken Sie. Zusammenführungen von Support zu Master führen immer zu Konflikten in der Datei mit den Versionsinformationen.

Wenn die Datei mit den Versionsinformationen nur die Versionsinformationen enthält, können Sie mit der Antwort von fcurella fortfahren. Aber wenn es tatsächlich auch zusammenführbare Informationen enthält (pom.xml, gradle.properties, MANIFEST.MF, ...), müssen Sie eine zusätzliche Aktion ausführen.

Verwenden wir das folgende Beispiel

      C---D*---E---F* support
     /
A---B---G---H*---I master

wobei Commits mit Sternen nur Änderungen aufgrund von Versionsänderungen enthalten, die beim Zusammenführen ignoriert werden sollten.

Um support mit master zusammenzuführen, ohne dass es aufgrund der Versionserstellung zu Zusammenführungskonflikten kommt, haben Sie folgende Möglichkeiten:

Mehrere Merge-Commits

git checkout master
git merge C
git merge D -s ours
git merge E
git merge F -s ours

Mit dem -s ours argument sagen wir git, nur eine Zusammenführung aufzuzeichnen, ohne den Arbeitsbereich zu verändern. Das ist vergleichbar mit dem --record-only Option von svn .

Das Obige führt zum folgenden Layout

      -------------C---D*---E---F* support
     /              \   \    \   \
A---B---G---H*---I---J---K----L---M master

Ein Merge-Commit mit Cherry-Pick

git checkout master
git merge support -s ours --no-commit
git cherry-pick C E --no-commit
git commit -m 'merged support into master'

zuerst starten wir eine Zusammenführung, aber nur den Datensatz, den wir zusammenführen, ohne den Arbeitsbereich zu ändern und ohne das Zusammenführungs-Commit auszuführen. Dann wählen wir die Commits aus, um sie wieder ohne Commit zusammenzuführen. Schließlich legen wir die Fusion fest.

Das Obige führt zum folgenden Layout

      C---D*---E---F* support
     /              \
A---B---G---H*---I---J master

Man könnte sogar das Kirschpflücken automatisieren.

git checkout master
git merge support -s ours --no-commit
for id in `git log support --reverse --not HEAD --format="%H [%an] %s" |
  grep -v "bump version" |
  sed "s/\(\w*\)\s.*/\1/g"`
do
  git cherry-pick --no-commit $id
done
git commit -m 'merged support into master'
15
Tobias Schulte

Der Grund, warum dies nicht direkt möglich ist, besteht darin, dass jedes Commit Links zu den übergeordneten Commits enthält (normalerweise nur eines, aber mehrere für Zusammenführungen). Auf diese Weise wird bei einem Commit (anhand der SHA1-Summe) auch der gesamte Verlauf festgelegt, da die Eltern auch Links zu ihren Eltern usw. enthalten. Die einzige Möglichkeit, Patches in der Historie auszulassen, besteht darin, ein neues zu schreiben. git rebase -i auf einem neu erstellten Zweig ist wahrscheinlich der einfachste Weg, dies zu erreichen.

4
user43563

Die Hauptfrage lautet: Wie möchten Sie die zu überspringenden Commits darstellen?

  1. hinterhältig verstecken (nicht mein Favorit)
  2. überspringen Sie diese explizit
  3. machen Sie sie explizit rückgängig

Unglücklicherweise nicht. 2 ist im Verlaufsdiagramm nicht auszudrücken.

1 ist möglich, aber ich würde niemals tun: Ein Merge-Commit kann Änderungen enthalten. - Normalerweise verweist ein Merge-Commit auf das Ergebnis der Zusammenführung von zwei weiteren Zweigen: Alle in diesen Zweigen entwickelten Elemente sollten sich nach der Zusammenführung im Code befinden (d. H. Im Code, auf den durch das Merge-Commit verwiesen wird). Und nichts anderes sollte in diesem Commit enthalten sein.

Aber Überraschung, Überraschung, Sie können die gesamte Codebasis ändern und als Zusammenführung darstellen. Das Zusammenführen hat zwei Auswirkungen: Es führt den Verlaufsbaum zusammen und es sollten zwei Codebasen zusammengeführt werden. Ersteres ist mit Sicherheit der Fall (andernfalls wird es von niemandem als Zusammenführung bezeichnet), letzteres kann fehlschlagen, z. Wenn ein Zusammenführungskonflikt auftrat und er falsch gelöst wurde (dann wurden die Codebasen nicht richtig zusammengeführt).

Einige der anderen Antworten schlagen dieses Verstecken vor. Ich empfehle den expliziten Weg: Zusammenführen und Zurücksetzen von Commits.

2
Robert Siemer

Es ist auch möglich, die Datei .git/info/attributes zu ändern und im Ordner .git zu belassen, anstatt überall .gitattribute-Dateien hinzuzufügen, die später zur Quellcodeverwaltung hinzugefügt werden müssen.

2
Kuznero

Wenn Sie nur einige Commits ausschließen möchten, die sich am Ende befinden, können Sie nur eine bestimmte Commit-Nummer festlegen:

git checkout partlyMergedFrom
git whatchanged
--> find the commit hash up to where you want to merge
git checkout partlyMergedInto
git merge e40a0e384f58409fe3c864c655a8d252b6422bfc
git whatchanged
--> check that you really got all the changes you want to have
1
Maze