Saya ingin mengganti nama / memindahkan subtree proyek di Git untuk memindahkannya
/project/xyz
untuk
/components/xyz
Jika saya menggunakan dataran git mv project components
, maka semua riwayat komit untuk xyz project
hilang. Apakah ada cara untuk memindahkan ini sedemikian rupa sehingga sejarah dipertahankan?
git mv
: stackoverflow.com/questions/1094269/whats-the-purpose-of-git-mvJawaban:
Git mendeteksi penggantian nama daripada mempertahankan operasi dengan komit, jadi apakah Anda menggunakan
git mv
ataumv
tidak masalah.The
log
perintah mengambil--follow
argumen yang terus sejarah sebelum operasi ganti nama, yaitu, mencari konten yang sama menggunakan heuristik:http://git-scm.com/docs/git-log
Untuk mencari riwayat lengkap, gunakan perintah berikut:
sumber
git config alias.logf "log --follow"
dan hanya menulisgit logf ./path/to/file
.Hal ini dimungkinkan untuk mengganti nama file dan menjaga sejarah utuh, meskipun hal itu menyebabkan file yang akan berganti nama di seluruh sejarah repositori. Ini mungkin hanya untuk pecinta git-log yang obsesif, dan memiliki beberapa implikasi serius, termasuk di antaranya:
Sekarang, karena Anda masih bersama saya, Anda mungkin seorang pengembang solo yang mengganti nama file yang sepenuhnya terisolasi. Mari kita pindahkan file menggunakan
filter-tree
!Asumsikan Anda akan memindahkan file
old
ke folderdir
dan berikan namanew
Ini bisa dilakukan dengan
git mv old dir/new && git add -u dir/new
, tetapi itu menghancurkan sejarah.Sebagai gantinya:
akan mengulang setiap komit di cabang, mengeksekusi perintah dalam kutu untuk setiap iterasi. Banyak hal yang bisa salah ketika Anda melakukan ini. Saya biasanya menguji untuk melihat apakah file tersebut ada (jika tidak belum ada di sana untuk pindah) dan kemudian melakukan langkah-langkah yang diperlukan untuk menyemir pohon sesuai keinginan saya. Di sini Anda dapat menelusuri file untuk mengubah referensi ke file dan sebagainya. Hancurkan dirimu! :)
Setelah selesai, file dipindahkan dan lognya utuh. Anda merasa seperti bajak laut ninja.
Juga; Dir mkdir hanya diperlukan jika Anda memindahkan file ke folder baru, tentu saja. The jika akan menghindari penciptaan folder ini sebelumnya dalam sejarah dari file Anda ada.
sumber
--index-filter
for for renames akan jauh lebih cepat karena pohon tidak harus diperiksa dan dikembalikan pada setiap komit.--index-filter
bertindak langsung pada setiap indeks komit.Tidak.
Jawaban singkatnya adalah TIDAK . Tidak mungkin untuk mengganti nama file di Git dan mengingat sejarahnya. Dan itu menyebalkan.
Rumor mengatakan bahwa itu
git log --follow
--find-copies-harder
akan berfungsi, tetapi itu tidak bekerja untuk saya, bahkan jika tidak ada perubahan pada isi file, dan langkah telah dilakukangit mv
.(Awalnya saya menggunakan Eclipse untuk mengganti nama dan memperbarui paket dalam satu operasi, yang mungkin membingungkan Git. Tetapi itu adalah hal yang sangat umum untuk dilakukan.
--follow
Tampaknya berfungsi jika hanyamv
dilakukan dan kemudian acommit
danmv
tidak terlalu jauh.)Linus mengatakan bahwa Anda seharusnya memahami seluruh isi proyek perangkat lunak secara holistik, tidak perlu melacak file individual. Sayangnya, otak kecil saya tidak bisa melakukan itu.
Benar- benar menjengkelkan karena begitu banyak orang dengan tanpa sadar mengulangi pernyataan bahwa Git secara otomatis melacak gerakan. Mereka telah menyia-nyiakan waktu saya. Git tidak melakukan hal seperti itu. Sesuai desain (!) Git tidak melacak pergerakan sama sekali.
Solusi saya adalah mengganti nama file kembali ke lokasi aslinya. Ubah perangkat lunak agar sesuai dengan kontrol sumber. Dengan Git Anda sepertinya perlu "git" dengan benar untuk pertama kali.
Sayangnya, itu memecah Eclipse, yang tampaknya digunakan
--follow
.git log --follow
terkadang tidak menunjukkan riwayat lengkap file dengan riwayat ganti nama yang rumit meskipungit log
demikian. (Saya tidak tahu kenapa.)(Ada beberapa peretasan yang terlalu cerdik yang kembali dan mengaktifkan kembali karya lama, tetapi agak menakutkan. Lihat GitHub-Gist: emiller / git-mv-with-history .)
sumber
akan menampilkan sejarah melalui penggantian nama.
sumber
git mv
pada dasarnya melakukan agit rm && git add
. Ada opsi seperti-M90
/--find-renames=90
untuk mempertimbangkan nama file yang akan diganti namanya saat 90% identik.Saya lakukan:
sumber
-A
sebagai gantinya? Sekali lagi, lihat di sini: git-scm.com/docs/git-addgit add -u
. Dokumen Git cenderung tidak membantu, dan merupakan tempat terakhir yang ingin saya lihat. Berikut ini satu pos yang ditampilkangit add -u
dalam aksi: stackoverflow.com/a/2117202 .Tidak (8 tahun kemudian, Git 2.19, Q3 2018), karena Git akan mendeteksi penggantian nama direktori , dan sekarang ini lebih baik didokumentasikan.
Lihat komit b00bf1c , komit 1634688 , komit 0661e49 , komit 4d34dff , komit 983f464 , komit c840e1a , komit 9929430 (27 Jun 2018), dan komit d4e8062 , komit 5dacd4a (25 Jun 2018) oleh Elijah Newren (
newren
) .(Digabung oleh Junio C Hamano -
gitster
- dalam komit 0ce5a69 , 24 Jul 2018)Itu sekarang dijelaskan dalam
Documentation/technical/directory-rename-detection.txt
:Contoh:
Tetapi ada banyak kasus lain, seperti:
Untuk menyederhanakan deteksi penggantian nama direktori, aturan tersebut diberlakukan oleh Git:
beberapa aturan dasar batas ketika deteksi ganti nama direktori berlaku:
Anda dapat melihat banyak tes
t/t6043-merge-rename-directories.sh
, yang juga menunjukkan bahwa:sumber
Objektif
git am
Batasan
Ringkasan
git log --pretty=email -p --reverse --full-index --binary
cat extracted-history | git am --committer-date-is-author-date
1. Ekstrak histori dalam format email
Contoh: Ekstrak riwayat
file3
,file4
danfile5
Atur / bersihkan tujuan
Ekstrak riwayat setiap file dalam format email
Sayangnya opsi
--follow
atau--find-copies-harder
tidak dapat digabungkan dengan--reverse
. Inilah sebabnya mengapa sejarah dipotong ketika file diganti namanya (atau ketika direktori induk diubah namanya).Riwayat sementara dalam format email:
Dan Bonachea menyarankan untuk membalikkan loop dari perintah pembuatan git log pada langkah pertama ini: daripada menjalankan git log sekali per file, jalankan persis sekali dengan daftar file pada baris perintah dan buat satu log tunggal. Dengan cara ini komit yang memodifikasi banyak file tetap menjadi komit tunggal dalam hasil, dan semua komit baru mempertahankan urutan relatif aslinya. Catatan ini juga membutuhkan perubahan pada langkah kedua di bawah ini ketika menulis ulang nama file di log (sekarang disatukan).
2. Atur kembali pohon file dan perbarui nama file
Misalkan Anda ingin memindahkan ketiga file ini di repo lain ini (bisa menjadi repo yang sama).
Karena itu atur ulang file Anda:
Riwayat sementara Anda sekarang:
Ubah juga nama file dalam riwayat:
3. Terapkan sejarah baru
Repo Anda yang lain adalah:
Terapkan komit dari file riwayat sementara:
--committer-date-is-author-date
mempertahankan stempel waktu komit asli ( komentar Dan Bonachea ).Repo Anda yang lain sekarang:
Gunakan
git status
untuk melihat jumlah komit yang siap didorong :-)Trik tambahan: Periksa file yang diubah namanya / dipindahkan dalam repo Anda
Untuk membuat daftar file yang telah diubah namanya:
Kustomisasi lainnya: Anda dapat menyelesaikan perintah
git log
menggunakan opsi--find-copies-harder
atau--reverse
. Anda juga dapat menghapus dua kolom pertama menggunakancut -f3-
dan menangkap pola lengkap '{. * =>. *}'.sumber
Saya mengikuti proses multi-langkah ini untuk memindahkan kode ke direktori induk dan menyimpan riwayat.
Langkah 0: Membuat 'sejarah' cabang dari 'master' untuk diamankan
Langkah 1: Menggunakan alat git-filter-repo untuk menulis ulang sejarah. Perintah ini di bawah ini memindahkan folder 'FolderwithContentOfInterest' ke satu tingkat dan memodifikasi riwayat komit yang relevan
Langkah 2: Pada saat ini repositori GitHub kehilangan jalur repositori jarak jauhnya. Referensi jarak jauh ditambahkan
Langkah 3: Tarik informasi tentang repositori
Langkah 4: Hubungkan cabang lokal yang hilang dengan cabang asal
Langkah 5: Alamat merge konflik untuk struktur folder jika diminta
Langkah 6: Dorong !!
Catatan: Riwayat yang diubah dan folder yang dipindahkan tampaknya sudah dikomit.
enter code here
Selesai Pindah kode ke direktori induk / yang dikehendaki menjaga riwayat tetap utuh!
sumber
Sementara inti dari Git, pipa Git tidak melacak nama, sejarah yang Anda tampilkan dengan log "porselen" Git dapat mendeteksi mereka jika Anda mau.
Untuk yang diberikan
git log
gunakan opsi -M:Dengan versi Git saat ini.
Ini berfungsi untuk perintah lain
git diff
juga.Ada beberapa opsi untuk membuat perbandingan lebih atau kurang ketat. Jika Anda mengganti nama file tanpa membuat perubahan signifikan pada file pada saat yang sama, itu membuat Git log dan teman-teman lebih mudah mendeteksi nama tersebut. Karena alasan ini beberapa orang mengganti nama file di satu komit dan mengubahnya di yang lain.
Ada biaya dalam penggunaan CPU setiap kali Anda meminta Git untuk menemukan di mana file telah diubah namanya, jadi apakah Anda menggunakannya atau tidak, dan kapan, terserah Anda.
Jika Anda ingin selalu memiliki riwayat Anda dilaporkan dengan deteksi nama dalam repositori tertentu, Anda dapat menggunakan:
Memindahkan file dari satu direktori ke yang lain adalah terdeteksi. Ini sebuah contoh:
Harap dicatat bahwa ini berfungsi setiap kali Anda menggunakan diff, bukan hanya dengan
git log
. Sebagai contoh:Sebagai percobaan saya membuat perubahan kecil dalam satu file di cabang fitur dan melakukan itu dan kemudian di cabang master saya mengubah nama file, melakukan, dan kemudian membuat perubahan kecil di bagian lain file dan melakukan itu. Ketika saya pergi ke fitur cabang dan bergabung dari master, gabungan tersebut mengganti nama file dan menggabungkan perubahan. Inilah output dari penggabungan:
Hasilnya adalah direktori yang berfungsi dengan nama file diubah dan kedua perubahan teks dibuat. Jadi mungkin bagi Git untuk melakukan hal yang benar meskipun faktanya itu tidak secara eksplisit melacak nama.
Ini adalah jawaban yang terlambat untuk pertanyaan lama sehingga jawaban yang lain mungkin benar untuk versi Git pada saat itu.
sumber
Pertama buat komit mandiri hanya dengan mengganti nama.
Kemudian setiap perubahan pada konten file dimasukkan ke dalam komit terpisah.
sumber
Untuk mengganti nama direktori atau file (saya tidak tahu banyak tentang kasus yang kompleks, jadi mungkin ada beberapa peringatan):
Untuk mengganti nama direktori dalam file yang menyebutkannya (dimungkinkan untuk menggunakan panggilan balik, tapi saya tidak tahu caranya):
expressions.txt
adalah file yang diisi dengan garis-garis sepertiliteral:OLD_NAME==>NEW_NAME
(dimungkinkan untuk menggunakan RE Python denganregex:
atau glob denganglob:
).Untuk mengganti nama direktori dalam pesan commit:
Ekspresi reguler Python juga didukung, tetapi harus ditulis dalam Python, secara manual.
Jika repositori asli, tanpa remote, Anda harus menambahkan
--force
untuk memaksa penulisan ulang. (Anda mungkin ingin membuat cadangan repositori Anda sebelum melakukan ini.)Jika Anda tidak ingin menyimpan referensi (akan ditampilkan dalam riwayat cabang Git GUI), Anda harus menambahkan
--replace-refs delete-no-add
.sumber
Cukup pindahkan file dan panggungnya dengan:
Sebelum komit, Anda dapat memeriksa status:
Itu akan menunjukkan:
Saya diuji dengan Git versi 2.26.1.
Diambil dari Halaman Bantuan GitHub .
sumber
Saya membuat memindahkan file dan kemudian melakukannya
yang menempatkan di area sataging semua file yang dihapus / baru. Di sini git menyadari bahwa file tersebut dipindahkan.
Saya tidak tahu mengapa tetapi ini berhasil untuk saya.
sumber