Come unire file specifici dai rami Git


179

Ho 2 rami git branch1 e branch2 e voglio unire file.py in branch2 in file.py in branch1 e solo quel file.

In sostanza, voglio solo lavorare su file.py in branch1 ma voglio sfruttare il comando merge. Qual è il modo migliore per farlo?



Risposte:


207

Quando il contenuto provienefile.py da branch2 che non si applica più a branch1 , è necessario selezionare alcune modifiche e lasciarne altre. Per un controllo completo, esegui un'unione interattiva usando l' --patchopzione:

$ git checkout --patch branch2 file.py

La sezione della modalità interattiva nella pagina man di git-add(1)spiega i tasti che devono essere usati:

y - stage this hunk
n - do not stage this hunk
q - quit; do not stage this hunk nor any of the remaining ones
a - stage this hunk and all later hunks in the file
d - do not stage this hunk nor any of the later hunks in the file
g - select a hunk to go to
/ - search for a hunk matching the given regex
j - leave this hunk undecided, see next undecided hunk
J - leave this hunk undecided, see next hunk
k - leave this hunk undecided, see previous undecided hunk
K - leave this hunk undecided, see previous hunk
s - split the current hunk into smaller hunks
e - manually edit the current hunk
? - print help

Il comando split è particolarmente utile.


3
Come possiamo usare la patch e allo stesso tempo usare uno strumento di unione? invece delle cose chiave
Gabriel

@Gabriel Ho usato Git anche con file patch e tarball perché è così facile creare un repository ( git init <dir>) e infine eliminarlo ( rm -r <dir>).
pdp,

105

Sebbene non sia un'unione di per sé, a volte è necessario l'intero contenuto di un altro file su un altro ramo. Il post sul blog di Jason Rudolph fornisce un modo semplice per copiare i file da un ramo all'altro. Applicare la tecnica come segue:

$ git checkout branch1 # ensure in branch1 is checked out and active
$ git checkout branch2 file.py

Ora file.pyè ora in branch1 .


91
Facile, ma in realtà non è una fusione . Sovrascrive solo file.pycon qualsiasi cosa sia nel ramo 2.
Greg Hewgill

Che cosa succede se unisci nuovamente il file da branch1 a branch2? Avrai conflitto!
Amir,

Questo conserva la cronologia dei commit?
C2H50H,

18

Nessuna delle altre risposte correnti "unirà" i file, come se si stesse utilizzando il comando unisci. (Nella migliore delle ipotesi, ti verrà richiesto di selezionare manualmente le differenze.) Se effettivamente vuoi trarre vantaggio dall'unione usando le informazioni di un antenato comune, puoi seguire una procedura basata su quella che si trova nella sezione "Unione avanzata" di git Manuale di riferimento.

Per questo protocollo, suppongo che tu voglia unire il file 'path / to / file.txt' da origin / master a HEAD - modificalo come appropriato. (Non devi essere nella directory principale del tuo repository, ma aiuta.)

# Find the merge base SHA1 (the common ancestor) for the two commits:
git merge-base HEAD origin/master

# Get the contents of the files at each stage
git show <merge-base SHA1>:path/to/file.txt > ./file.common.txt
git show HEAD:path/to/file.txt > ./file.ours.txt
git show origin/master:path/to/file.txt > ./file.theirs.txt

# You can pre-edit any of the files (e.g. run a formatter on it), if you want.

# Merge the files
git merge-file -p ./file.ours.txt ./file.common.txt ./file.theirs.txt > ./file.merged.txt

# Resolve merge conflicts in ./file.merged.txt
# Copy the merged version to the destination
# Clean up the intermediate files

git merge-file dovrebbe usare tutte le impostazioni di unione predefinite per la formattazione e simili.

Si noti inoltre che se la "nostra" è la versione della copia funzionante e non si desidera essere eccessivamente cauti, è possibile operare direttamente sul file:

git merge-base HEAD origin/master
git show <merge-base SHA1>:path/to/file.txt > ./file.common.txt
git show origin/master:path/to/file.txt > ./file.theirs.txt
git merge-file path/to/file.txt ./file.common.txt ./file.theirs.txt

15

Tutte le modifiche sono file.pyin branch2proprio commit, separate dalle modifiche ad altri file? In tal caso, puoi semplicemente cherry-pickmodificare le modifiche:

git checkout branch1
git cherry-pick <commit-with-changes-to-file.py>

Altrimenti, mergenon funziona su singoli percorsi ... potresti anche creare una git diffpatch di file.pymodifiche da branch2e git applyloro a branch1:

git checkout branch2
git diff <base-commit-before-changes-to-file.py> -- file.py > my.patch
git checkout branch1
git apply my.patch

8

Puoi stashe stash popil file:

git checkout branch1
git checkout branch2 file.py
git stash
git checkout branch1
git stash pop

Questo sovrascrive branch1 / file.py con il contenuto di branch2 / file.py invece di un'unione che dovrebbe sollevare un conflitto di unione da risolvere.
plumSemPy,

2

Per unire solo le modifiche da branch2 file.py, fai scomparire le altre modifiche.

git checkout -B wip branch2
git read-tree branch1
git checkout branch2 file.py
git commit -m'merging only file.py history from branch2 into branch1'
git checkout branch1
git merge wip

L'unione non guarderà nemmeno nessun altro file. Potrebbe essere necessario '-f' i checkout se gli alberi sono abbastanza diversi.

Nota che questo lascerà branch1 come se tutto nella storia di branch2 a quel punto fosse stato unito, che potrebbe non essere quello che vuoi. Una versione migliore del primo checkout sopra è probabilmente

git checkout -B wip `git merge-base branch1 branch2`

nel qual caso probabilmente dovrebbe essere anche il messaggio di commit

git commit -m"merging only $(git rev-parse branch2):file.py into branch1"

0

Sono nella stessa situazione, voglio unire un file da un ramo che ha molti commit su di esso su 2 rami. Ho provato molti modi sopra e altri che ho trovato su Internet e tutti hanno fallito (perché la cronologia del commit è complessa), quindi decido di fare la mia strada (la strada folle).

git merge <other-branch>
cp file-to-merge file-to-merge.example
git reset --hard HEAD (or HEAD^1 if no conflicts happen)
cp file-to-merge.example file-to-merge

0

Quello che ho fatto è un po 'manuale, ma io:

  1. Fuse i rami normalmente; Ripristinata l'unione con revert;
  2. Ho verificato tutti i miei file HEAD~1, ovvero il loro stato nel commit di unione;
  3. Ho reimpostato il mio impegno per nascondere questa pirateria informatica nella cronologia degli impegni.

Brutta? Sì. Facile da ricordare? Anche si.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.