Bagaimana cara memperbaiki subtree git setelah kekuatan proyek hulu didorong ke master?

13

Saya telah bereksperimen dengan menggunakan subtree git dan telah mengalami situasi berikut.

Saya menggunakan subtree git untuk menambahkan proyek eksternal ke repo saya, saya sengaja menyimpan semua sejarah untuk proyek hulu karena saya ingin dapat merujuk ke sejarah proyek dan juga berkontribusi kembali ke proyek hulu nanti.

Ternyata, kontributor lain untuk proyek upstream secara tidak sengaja mendorong file besar ke cabang master. Untuk mengatasinya, proyek hulu menulis ulang sejarah dan kekuatan didorong ke master. Saat membuat "monorepo" saya, saya menyertakan komit ini dan saya juga ingin menghapusnya.

Bagaimana saya bisa memperbarui repositori saya untuk mencerminkan sejarah baru subtree?

Upaya pertama saya adalah menggunakan cabang-filter untuk sepenuhnya menghapus subtree dan semua riwayat.

git filter-branch --index-filter 'git rm -rf --cached --ignore-unmatch upstream-project-dir' --prune-empty HEAD

Setelah versi subtree lama dihapus, saya bisa menambahkan ulang subtree menggunakan master hulu yang baru. Namun, ini tidak berhasil karena untuk beberapa alasan sejarah komit masih muncul di git log output.

Memperbarui

Saya telah menulis langkah-langkah untuk membuat contoh yang dapat direproduksi secara minimal.

  1. Pertama buat git repo kosong.

    git init test-monorepo
    cd ./test-monorepo
    
  2. Buat komit awal.

    echo hello world > README
    git add README
    git commit -m 'initial commit'
    
  3. Sekarang tambahkan subtree untuk proyek eksternal.

    git remote add thirdparty [email protected]:teivah/algodeck.git
    git fetch thirdparty
    git subtree add --prefix algodeck thirdparty master
    
  4. Buat beberapa komitmen di monorepo

    echo dont panic >> algodeck/README.md
    git commit -a -m 'test commit'
    
  5. Sekarang coba gunakan cabang-filter git untuk menghapus subtree.

    git filter-branch --index-filter 'git rm -rf --cached --ignore-unmatch algodeck' --prune-empty HEAD
    
  6. Memeriksa output log git, saya berharap hanya melihat komit awal saya.

    git log
    
csnate
sumber
Sudahkah Anda mencoba git gc --prune = sekarang untuk membuang commit lama? Apakah ada beberapa referensi yang dilakukan oleh versi lama?
Damiano
1
Saya belum mencoba ini, tetapi tidak akan git gc --prune=nowhanya menghapus komit yang tidak muncul git log?
csnate
menggunakan cabang git -semua (yang saya kira Anda gunakan untuk melihat komit "lama") harus menunjukkan juga komit yang tidak terkait dengan cabang Anda saat ini.
Damiano
1
Sebenarnya, saya hanya melakukan git log, tidak ada argumen dan saya masih melihat komitmen lama.
csnate
Bisakah Anda memposting git log --pretty --all --graph? Hanya untuk memahami situasi Anda
Damiano

Jawaban:

0

Anda sudah mendapatkan komitmen buruk dalam riwayat Anda dan Anda harus menyingkirkannya sebelum melanjutkan

mari kita asumsikan Anda memiliki masterkomit terakhir dialihkan dan belum dapat melakukan hal lain (saya benar-benar tidak memiliki cabang Anda di depan mata, jadi saya perlu mengasumsikan sesuatu untuk memulai dengan)

Anda dapat checkout ke komit sebelumnya dan mendorong penanda cabang Anda 1 langkah mundur (atau X langkah mundur) yang tidak akan berbahaya dalam hal apa pun dan kemudian tarik lagi

misalnya

git checkout master~1
git branch master -f
git checkout master
git pull
  1. git checkout master~1 untuk memeriksa komitmen induk, git memperingatkan kita dari cabang
  2. git branch master -f untuk memaksa checkout saat ini untuk menjadi master lagi, yaitu benar-benar memutar ulang cabang master ke komit sebelumnya (atau X komit sebelumnya), dan dari sini, tidak masalah apakah hulu melakukan kekuatan atau tidak, kita dapat melanjutkan secara normal, atau bahkan kembali ke langkah di atas jika diperlukan, kita hanya dapat menarik master lagi, tanpa kehilangan apa pun dari hulu (yang bagi kita bisa dibaca-saja juga, kita tidak akan mendorong apa pun untuk ini)
  3. git checkout master untuk berada di cabang master "rewound" kami, komit yang sama dengan yang kami tuju, tetapi sekarang berada di cabang
  4. git pulluntuk menarik master lagi (bisa dengan atau tanpa --prune), jika hulu dialihkan, kita akan kembali ke jalur dari sini, jika tidak, kita akan mendapatkan yang sama yang kita miliki, jika kita mendapatkan yang sama dan tidak seharusnya, mungkin kita perlu kembali ke langkah 1 di atas dan memundurkan lebih banyak komitmen, misalnya git checkout master~5atau apa pun (sesuai kebutuhan)
arhak
sumber
Saya rasa ini tidak akan berhasilgit subtree
csnate
@csnate dimungkinkan untuk melakukan checkout komit sebelumnya dari subrepo dan mengikuti prosedur yang sangat mirip, jika Anda membangun MCVE akan lebih mudah untuk memberi tahu Anda perintah yang tepat untuk mengikuti stackoverflow.com/help/minimal-reproducible-example
arhak
Saya akan mencoba membuat repo sampel di GitHub.
csnate
Saya membuat serangkaian langkah dalam pertanyaan awal yang menunjukkan masalah ini.
csnate
0
  1. pada repo Anda, bersihkan riwayat commit untuk remote ini:

    git fetch upstream
    
  2. jika salah satu dari komit Anda memiliki komit yang menyertakan file besar, tulis ulang riwayat Anda sehingga file besar ini tidak lagi direferensikan

    # using one or more of the following commands :
    git rebase --interactive
    git filter-branch
    ...
    

Dengan dua langkah ini, file besar tidak akan direferensikan lagi oleh komit di repo Anda.
Ini juga akan dihapus dari hard drive Anda pada suatu saat, ketika git menjalankan pengumpul sampahnya dan penundaan kadaluarsa untuk gumpalan yang menggantung telah tercapai.


Jika Anda memiliki kebutuhan mendesak untuk menghapus file besar ini ASAP dari hard drive Anda:

Lari secara manual

git gc --prune=now
LeGEC
sumber