1812 Stimmen

Wie kann ich in Git selektiv Änderungen aus einem anderen Zweig zusammenführen oder auswählen?

Ich verwende Git für ein neues Projekt, das zwei parallele - aber derzeit experimentelle - Entwicklungszweige hat:

  • master Import der bestehenden Codebasis plus einige Änderungen, bei denen ich mir im Allgemeinen sicher bin
  • exp1 : Versuchszweig #1
  • exp2 : Versuchszweig #2

exp1 y exp2 stehen für zwei sehr unterschiedliche Architekturansätze. Solange ich nicht weitergekommen bin, kann ich nicht wissen, welcher Ansatz (wenn überhaupt) funktionieren wird. Wenn ich in einem Zweig Fortschritte mache, habe ich manchmal Bearbeitungen, die im anderen Zweig nützlich wären, und möchte genau diese zusammenführen.

Was ist der beste Weg, um selektive Änderungen von einem Entwicklungszweig in einen anderen zusammenzuführen und dabei alles andere zurückzulassen?

Ansätze, die ich in Betracht gezogen habe:

  1. git merge --no-commit gefolgt von der manuellen Freigabe einer großen Anzahl von Bearbeitungen, die ich nicht zwischen den Zweigen austauschen möchte.

  2. Manuelles Kopieren von gemeinsamen Dateien in ein temporäres Verzeichnis, gefolgt von git checkout um in den anderen Zweig zu wechseln und dann mehr manuelles Kopieren aus dem temporären Verzeichnis in den Arbeitsbaum.

  3. Eine Abwandlung des obigen Beispiels. Verzichten Sie auf die exp Zweigen und verwenden Sie zwei zusätzliche lokale Repositories für Experimente. Dies macht das manuelle Kopieren von Dateien viel einfacher.

Alle drei Ansätze erscheinen mühsam und fehleranfällig. Ich hoffe, dass es einen besseren Ansatz gibt; so etwas wie einen Filterpfad-Parameter, der die git-merge wählerischer.

5voto

Dave C Punkte 1134

Ein einfacher Ansatz für das selektive Zusammenführen/Übertragen nach Dateien:

git checkout dstBranch
git merge srcBranch

// Make changes, including resolving conflicts to single files
git add singleFile1 singleFile2
git commit -m "message specific to a few files"
git reset --hard # Blow away uncommitted changes

5voto

Andy Punkte 4948

Ich habe mein eigenes Skript namens 'pmerge' geschrieben, um Verzeichnisse teilweise zusammenzuführen. Es ist noch in Arbeit und ich lerne immer noch sowohl Git als auch die Bash-Skripterstellung.

Dieser Befehl verwendet git merge --no-commit und hebt dann Änderungen auf, die nicht mit dem angegebenen Pfad übereinstimmen.

Verwendung: git pmerge branch path
Beispiel: git merge develop src/

Ich habe es nicht ausgiebig getestet. Das Arbeitsverzeichnis sollte frei von unübertragenen Änderungen und nicht verfolgten Dateien sein.

#!/bin/bash

E_BADARGS=65

if [ $# -ne 2 ]
then
    echo "Usage: `basename $0` branch path"
    exit $E_BADARGS
fi

git merge $1 --no-commit
IFS=$'\n'

# List of changes due to merge | replace nulls with newlines | strip lines to just filenames | ensure lines are unique
for f in $(git status --porcelain -z -uno | tr '\000' '\n' | sed -e 's/^[[:graph:]][[:space:]]\{1,\}//' | uniq); do
    [[ $f == $2* ]] && continue
    if git reset $f >/dev/null 2>&1; then
        # Reset failed... file was previously unversioned
        echo Deleting $f
        rm $f
    else
        echo Reverting $f
        git checkout -- $f >/dev/null 2>&1
    fi
done
unset IFS

4voto

JBaczuk Punkte 12476

Wenn Sie nicht allzu viele Dateien geändert haben, werden Sie keine zusätzlichen Übertragungen vornehmen müssen.

1. Zweig vorübergehend duplizieren
$ git checkout -b temp_branch

2. Zurücksetzen auf die letzte gewünschte Übertragung
$ git reset --hard HEAD~n , donde n ist die Anzahl der Commits, die Sie zurückgehen müssen

3. Jede Datei aus dem ursprünglichen Zweig auschecken
$ git checkout origin/original_branch filename.ext

Jetzt können Sie bei Bedarf eine Übergabe durchführen und einen Push erzwingen (um remote zu überschreiben).

3voto

raratiru Punkte 7315

Wenn sich nur wenige Dateien zwischen den aktuellen Übertragungen der beiden Zweige geändert haben, führe ich die Änderungen manuell zusammen, indem ich die verschiedenen Dateien durchgehe.

git difftool <branch-1>..<branch-2>

siehe auch https://sites.google.com/site/icusite/setup/git-difftool

3voto

code4kix Punkte 3475

Wenn Sie nur ein bestimmtes Verzeichnis zusammenführen müssen und alles andere intakt lassen und dennoch die Historie erhalten wollen, könnten Sie Folgendes versuchen... erstellen Sie ein neues target-branch von der master bevor Sie experimentieren.

Die folgenden Schritte gehen davon aus, dass Sie zwei Zweige haben target-branch y source-branch und das Verzeichnis dir-to-merge die Sie zusammenführen möchten, befindet sich in der source-branch . Nehmen Sie auch an, dass Sie andere Verzeichnisse haben wie dir-to-retain in dem Ziel, das Sie nicht ändern wollen, und behalten Sie die Geschichte. Angenommen, es gibt Merge-Konflikte in der dir-to-merge .

git checkout target-branch
git merge --no-ff --no-commit -X theirs source-branch
# the option "-X theirs", will pick theirs when there is a conflict. 
# the options "--no--ff --no-commit" prevent a commit after a merge, and give you an opportunity to fix other directories you want to retain, before you commit this merge.

# the above, would have messed up the other directories that you want to retain.
# so you need to reset them for every directory that you want to retain.
git reset HEAD dir-to-retain
# verify everything and commit.

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