Cara menggabungkan file tertentu dari cabang Git

179

Saya punya 2 git, branch1 dan branch2 dan saya ingin menggabungkan file.py di branch2 menjadi file.py di branch1 dan hanya file itu.

Intinya saya hanya ingin bekerja pada file.py di branch1 tetapi ingin memanfaatkan perintah gabungan. Apa cara terbaik untuk melakukan ini?

rwolst
sumber

Jawaban:

207

Ketika konten dalam file.pydari branch2 yang tidak lagi berlaku untuk branch1 , itu memerlukan memilih beberapa perubahan dan meninggalkan yang lain. Untuk kontrol penuh lakukan penggabungan interaktif menggunakan --patchsakelar:

$ git checkout --patch branch2 file.py

Bagian mode interaktif di halaman manual untuk git-add(1)menjelaskan kunci yang akan digunakan:

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

Perintah split sangat berguna.

pdp
sumber
3
Bagaimana kita bisa menggunakan tambalan dan pada saat yang sama menggunakan alat gabungan? bukannya hal
Gabriel
@Gabriel Saya telah menggunakan Git bahkan dengan file patch dan tarballs karena sangat mudah untuk membuat repo ( git init <dir>) dan akhirnya membuangnya ( rm -r <dir>).
pdp
105

Meskipun bukan gabungan , terkadang seluruh isi file lain di cabang lain diperlukan. Jason RudolphPosting blog menyediakan cara sederhana untuk menyalin file dari satu cabang ke cabang lainnya. Terapkan teknik ini sebagai berikut:

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

Sekarang file.pysekarang di branch1 .

Matthew Turner
sumber
91
Mudah, tapi itu sebenarnya bukan gabungan . Itu hanya menimpa file.pydengan apa pun yang ada di cabang 2.
Greg Hewgill
Bagaimana jika Anda menggabungkan kembali file dari branch1 ke branch2? Anda akan mendapat konflik!
Amir
Apakah ini mempertahankan riwayat komit?
C2H50H
18

Tidak ada jawaban lain saat ini yang benar-benar akan "menggabungkan" file, seolah-olah Anda menggunakan perintah gabung. (Paling-paling mereka akan mengharuskan Anda untuk memilih secara manual.) Jika Anda benar-benar ingin mengambil keuntungan dari penggabungan menggunakan informasi dari leluhur yang sama, Anda dapat mengikuti prosedur berdasarkan prosedur yang ditemukan di bagian "Penggabungan Lanjut" pada git Manual Referensi.

Untuk protokol ini, saya berasumsi Anda ingin menggabungkan file 'path / to / file.txt' dari origin / master ke HEAD - modifikasi yang sesuai. (Anda tidak harus berada di direktori teratas repositori Anda, tetapi itu membantu.)

# 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 harus menggunakan semua pengaturan penggabungan default Anda untuk pemformatan dan sejenisnya.

Perhatikan juga bahwa jika "milik kami" adalah versi salin yang berfungsi dan Anda tidak ingin terlalu berhati-hati, Anda dapat beroperasi langsung di 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
RM
sumber
15

Apakah semua modifikasi dilakukan file.pydalam branch2komitmen mereka sendiri, terpisah dari modifikasi ke file lain? Jika demikian, Anda dapat dengan mudah cherry-pickmengubah:

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

Jika tidak, mergetidak beroperasi di jalur individual ... Anda mungkin juga membuat git diffpatch file.pyperubahan dari branch2dan git applymereka ke branch1:

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

sumber
8

Anda dapat stashdan stash popfile:

git checkout branch1
git checkout branch2 file.py
git stash
git checkout branch1
git stash pop
Martin G
sumber
Ini menimpa branch1 / file.py dengan konten branch2 / file.py bukan gabungan yang harus meningkatkan konflik gabungan untuk diselesaikan.
plumSemPy
2

Untuk menggabungkan hanya perubahan dari branch2 file.py, buat perubahan lainnya hilang.

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

Penggabungan bahkan tidak akan pernah melihat file lain. Anda mungkin perlu '-f' checkout jika pohon cukup berbeda.

Perhatikan bahwa ini akan membuat branch1 tampak seolah-olah semua yang ada dalam sejarah branch2 sampai saat itu telah digabung, yang mungkin bukan yang Anda inginkan. Versi checkout pertama yang lebih baik di atas mungkin

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

dalam hal ini pesan komit mungkin juga harus

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

Saya dalam situasi yang sama, saya ingin menggabungkan file dari cabang yang memiliki banyak komit di 2 cabang. Saya mencoba banyak cara di atas dan lainnya saya temukan di internet dan semuanya gagal (karena komit sejarah itu kompleks) jadi saya memutuskan untuk melakukan cara saya (cara gila).

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
Trac Nguyen
sumber
0

Apa yang saya lakukan adalah sedikit manual, tetapi saya:

  1. Menggabungkan cabang secara normal; Kembalikan penggabungan dengan revert;
  2. Memeriksa semua file saya ke HEAD~1, yaitu, negara mereka di komit gabungan;
  3. Mengubah komitmen saya untuk menyembunyikan peretasan ini dari riwayat commit.

Jelek? Iya. Mudah diingat? Juga ya.

Lucas Lima
sumber