Bagaimana cara mengubah repositori Git normal ke yang telanjang?

603

Bagaimana saya bisa mengubah repositori Git 'normal' menjadi yang telanjang?

Perbedaan utama tampaknya adalah:

  • di repositori Git yang normal, Anda memiliki .gitfolder di dalam repositori yang berisi semua data yang relevan dan semua file lainnya yang merupakan copy pekerjaan Anda

  • di repositori telanjang Git, tidak ada copy yang berfungsi dan folder (sebut saja repo.git) berisi data repositori yang sebenarnya

Boldewyn
sumber
16
Agaknya ini adalah metode yang lebih pendek:mv repo/.git repo.git; rm -rf repo
jameshfisher
Ya benar. Ketika saya menulis pertanyaan, ini hanya potongan sejarah saya, yang saya eksekusi pada menit berikutnya.
Boldewyn
54
@ eegg Gunakan &&sebagai ganti ;jika mvgagal!

Jawaban:

610

Singkatnya: ganti konten repodengan konten repo/.git, lalu beri tahu repositori bahwa itu sekarang adalah repositori kosong.

Untuk melakukan ini, jalankan perintah berikut:

cd repo
mv .git ../repo.git # renaming just for clarity
cd ..
rm -fr repo
cd repo.git
git config --bool core.bare true

Perhatikan bahwa ini berbeda dengan melakukan a git clone --bareke lokasi baru (lihat di bawah).

Jörg W Mittag
sumber
9
Terima kasih atas petunjuknya core.bare. Sekarang, setelah googling opsi ini, saya dapat mengkonfirmasinya: kernel.org/pub/software/scm/git-core/docs/git-config.html
Boldewyn
14
Terima kasih! Ini tampak lebih bersih bagi saya: mv repo / .git repo.git &&rm -rf repo && cd repo.git && git config --bool core.bare true
JasonWoof
56
Ini jauh lebih rumit dan rapuh daripada jawaban di bawah ini ( git clone --bare /path/to/repo).
DJJ
7
Itu rmperintah mungkin perlu * \.[!.]*bukan *dalam rangka untuk menghapus dot-file dan dot-direktori.
minopret
6
@Ciantic: Sekali lagi, seperti yang sudah saya jelaskan di komentar saya di atas, jawaban saya diberikan 3 tahun yang lalu, tetapi 5 bulan yang lalu seseorang mengedit pertanyaan itu menjadi sesuatu yang sama sekali berbeda. Tak satu pun dari jawaban di halaman ini akan membuat setiap akal lagi. Urutan perintah itu langsung disalin dari pertanyaan, saya baru saja menambahkan dua baris terakhir.
Jörg W Mittag
244

Metode Anda sepertinya akan berhasil; struktur file dari repositori kosong adalah apa yang ada di dalam direktori .git. Tapi saya tidak tahu apakah ada file yang benar-benar berubah, jadi jika itu gagal, Anda bisa melakukannya

git clone --bare /path/to/repo

Anda mungkin harus melakukannya di direktori lain untuk menghindari konflik nama, dan kemudian Anda bisa memindahkannya kembali ke tempat yang Anda inginkan. Dan Anda mungkin perlu mengubah file konfigurasi untuk menunjuk ke mana pun repo asal Anda berada.

jonescb
sumber
50
Salah, metode ini tidak setara. Melakukan klon tidak mempertahankan opsi konfigurasi, yang bisa sangat penting untuk operasi yang benar seperti jika Anda menggunakan git-p4. Selain itu, klon menghancurkan remote, lagi dengan sesuatu seperti git-p4 Anda kehilangan cabang p4 / master saat Anda mengkloning, jadi pendekatan di atas lebih disukai.
nosatalian
26
Tetapi Anda dapat mentransfer opsi konfigurasi dengan mudah dengan menyalin masing-masing bagian file konfigurasi. Saya masih menganggap metode ini lebih bersih daripada menyalin dan mengganti nama file secara manual.
Philipp
6
Ini sempurna setelah migrasi subversi karena git-svn tidak memiliki dukungan untuk --bare.
Keyo
11
Untuk menghindari konflik nama ---git clone --bare /path/to/repo.git /path/to/newbarerepo.git
raksja
Ini berfungsi selama Anda menjalankan git update-server-inforepo telanjang setelah penciptaan.
ACK_stoverflow
116

Saya pikir tautan berikut ini akan sangat membantu

GitFaq: Bagaimana cara membuat repositori non-telanjang yang ada?

$ mv repo/.git repo.git
$ git --git-dir=repo.git config core.bare true
$ rm -rf repo
xhh
sumber
2
Ya, itu yang saya cari, terima kasih! Namun, proposal kedua mereka ( git clone) memiliki kelemahan yang nosatalian disebutkan di atas.
Boldewyn
1
Dokumentasi yang Anda sarankan selanjutnya mengatakan, "Metode yang lebih aman adalah membiarkan Git menangani semua pengaturan internal untuk Anda dengan melakukan sesuatu seperti ini ... git clone --bare -l <path_to_repos> <new_dir>"
dafunker
74

Kecuali Anda secara khusus ingin atau perlu memutar-mutar bit pada sistem file, itu benar-benar sederhana untuk membuat versi telanjang dari repositori non-telanjang (disebutkan dalam beberapa posting lain di sini). Itu bagian dari fungsionalitas inti git:

git clone --bare existing_repo_path bare_repo_path

Chip Kaye
sumber
6
Agak luar biasa bahwa jawaban terbaik jauh-dan-jauh memiliki 0 suara setelah> 4 bulan. 'Jawaban yang diterima' yang tidak-sangat-baik-tetapi-berbahaya memiliki 200!
Stabledog
36
Sama sekali tidak luar biasa - jawaban ini tidak sesuai dengan pertanyaan awal. Itu tidak mengkonversi repo, itu klon satu, kehilangan informasi dalam proses (misalnya, cabang jarak jauh).
GreenAsJade
15

Harap pertimbangkan untuk menggunakan

git clone --mirror path_to_source_repository

Dari dokumentasi :

Siapkan cermin repositori sumber. Ini menyiratkan --bare. Dibandingkan dengan --bare, --mirror tidak hanya memetakan cabang lokal dari sumber ke cabang lokal dari target, ia memetakan semua referensi (termasuk cabang pelacakan jarak jauh, catatan, dll.) Dan membuat konfigurasi refspec sehingga semua referensi ini ditimpa oleh pembaruan git remote di repositori target.

Jacek Krawczyk
sumber
Sepertinya ini adalah cara yang paling ringkas, lengkap dan aman untuk melakukan apa yang diinginkan OP (vs. adil clone). Apakah saya melewatkan sesuatu? Apakah --mirrorpenambahan yang relatif baru?
Craig Silver
@CraigSilver: Tidak, seperti yang saya lihat dalam sejarah dokumentasi dalam bentuk seperti --mirroritu tersedia dari versi 1.7, jadi sudah cukup lama. Anda dapat memeriksa di sini
Jacek Krawczyk
7

Saya hanya ingin mendorong repositori di jalur jaringan tetapi git tidak akan membiarkan saya melakukan itu kecuali repositori itu ditandai sebagai telanjang. Yang saya butuhkan adalah mengubah konfigurasi:

git config --bool core.bare true

Tidak perlu mengutak-atik file kecuali Anda ingin tetap bersih.

Slion
sumber
3
Ini berbahaya, ketika Anda juga ingin bekerja di pohon kerja repo jarak jauh. Kemungkinannya adalah bahwa cepat atau lambat Anda mengembalikan perubahan hanya karena pohon kerja jarak jauh dan indeks Anda tidak sinkron dengan repositori. Saya tidak merekomendasikan solusi ini, jika Anda tidak tahu persis apa yang Anda lakukan.
Boldewyn
Benar, Anda seharusnya tidak bekerja pada pohon repo telanjang.
Slion
6

saya sudah membaca jawabannya dan saya sudah melakukan ini:

cd repos
mv .git repos.git
cd repos.git
git config --bool core.bare true # from another answer
cd ../
mv repos.git ../
cd ../
rm -rf repos/ # or delete using a file manager if you like

ini akan meninggalkan konten repos/.gitsebagai yang telanjangrepos.git

Dan D.
sumber
4

Inilah yang menurut saya paling aman dan paling sederhana. Tidak ada apa pun di sini yang tidak disebutkan di atas. Saya hanya ingin melihat jawaban yang menunjukkan prosedur langkah demi langkah yang aman. Anda memulai satu folder dari repositori (repo) yang ingin Anda buat kosong. Saya telah mengadopsi konvensi yang tersirat di atas bahwa folder repositori kosong memiliki ekstensi .git.

(1) Backup, just in case.
    (a) > mkdir backup
    (b) > cd backup
    (c) > git clone ../repo
(2) Make it bare, then move it
    (a) > cd ../repo
    (b) > git config --bool core.bare true
    (c) > mv .git ../repo.git
(3) Confirm the bare repository works (optional, since we have a backup)
    (a) > cd ..
    (b) > mkdir test
    (c) > cd test
    (d) > git clone ../repo.git
(4) Clean up
    (a) > rm -Rf repo
    (b) (optional) > rm -Rf backup/repo
    (c) (optional) > rm -Rf test/repo
sdesciencelover
sumber
1
ini tidak terlalu aman karena Anda membuat cadangan menggunakan git clone. Pencadangan dengan kloning akan menyebabkan Anda kehilangan beberapa konfigurasi, yang dalam beberapa kasus tertentu mungkin penting untuk repositori.
Lie Ryan
Dicatat. Satu-satunya konfigurasi yang pernah saya pedulikan adalah global untuk semua repositori lokal saya.
sdesciencelover
4

Cukup baca

Buku Pro Git: 4.2 Git di Server - Mendapatkan Git di Server

yang melambung ke

$ git clone --bare my_project my_project.git
Cloning into bare repository 'my_project.git'...
done.

Kemudian masukkan my_project.git ke server

Yang terutama adalah, apa jawaban # 42 coba . Shurely seseorang dapat menemukan kembali roda ;-)

apos
sumber
Saya gagal melihat, apa yang ditambahkan jawaban ini, yang belum dibahas panjang lebar dalam jawaban lain mana pun di sekitar (termasuk yang diturunkan). Bisakah Anda menjelaskan? (Ngomong-ngomong: Pro Git Book mengatakan, "Ini kira-kira setara dengan sesuatu seperti ..." , dan bahwa kesetaraan kasar yang tepat juga sudah dibahas di sini.)
Boldewyn
3

Berikut adalah fungsi BASH kecil yang dapat Anda tambahkan ke .bashrc atau .profile Anda pada sistem berbasis UNIX. Setelah ditambahkan dan shell di-restart atau file dimuat ulang melalui panggilan ke source ~/.profileatau source ~/.bashrc.

function gitToBare() {
  if [ -d ".git" ]; then
    DIR="`pwd`"
    mv .git ..
    rm -fr *
    mv ../.git .
    mv .git/* .
    rmdir .git

    git config --bool core.bare true
    cd ..
    mv "${DIR}" "${DIR}.git"

    printf "[\x1b[32mSUCCESS\x1b[0m] Git repository converted to "
    printf "bare and renamed to\n  ${DIR}.git\n"
    cd "${DIR}.git"
  else
    printf "[\x1b[31mFAILURE\x1b[0m] Cannot find a .git directory\n"
  fi
}

Setelah dipanggil di dalam direktori yang berisi direktori .git, itu akan membuat perubahan yang sesuai untuk mengubah repositori. Jika tidak ada direktori .git saat dipanggil, pesan FAILURE akan muncul dan tidak ada perubahan sistem file yang akan terjadi.

nyteshade
sumber
1

Metode yang mengatakan untuk menghapus file dan membuang sekitar dengan memindahkan direktori .git tidak bersih dan tidak menggunakan metode "git" dalam melakukan sesuatu yang seharusnya sederhana. Ini adalah metode terbersih yang saya temukan untuk mengubah repo normal menjadi repo kosong.

Klon pertama / path / ke / normal / repo ke repo telanjang yang disebut repo.git

git clone --bare /path/to/normal/repo

Selanjutnya hapus asal yang menunjuk ke / path / ke / normal / repo

cd repo.git
git remote rm origin

Akhirnya Anda dapat menghapus repo asli Anda. Anda bisa mengganti nama repo.git menjadi repo pada saat itu, tetapi konvensi standar untuk menandakan repositori git adalah sesuatu.gas, jadi saya pribadi akan membiarkannya begitu.

Setelah Anda melakukan semua itu, Anda dapat mengkloning bare repo baru Anda (yang pada dasarnya menciptakan repo normal, dan juga bagaimana Anda akan mengubahnya dari bare ke normal)

Tentu saja jika Anda memiliki upstream baru, Anda ingin membuat catatan tentang mereka, dan memperbarui repo telanjang Anda untuk memasukkannya. Tetapi sekali lagi, semuanya bisa dilakukan dengan perintah git. Ingat halaman manual adalah teman Anda.

krux
sumber
1
Pernahkah Anda repot membaca jawaban yang lain? Terutama komentar @ jonescb dan @ nosatalian? Metode "git" adalah ini: "Lakukan sebanyak mungkin dengan file teks biasa". Anda harus mulai menyelidiki bagian dalam .gitfolder. Sangat mendidik untuk belajar, bagaimana bagian-bagiannya saling bersesuaian.
Boldewyn
1

Jika Anda memiliki repositori dengan beberapa cabang checkout lokal / ref / head / * dan beberapa cabang remote remote / origin / * DAN jika Anda ingin mengubahnya menjadi repositori BARE dengan semua cabang di / ref / head / *

Anda dapat melakukan yang berikut untuk menyimpan riwayat.

  1. buat repositori kosong
  2. cd ke dalam repositori lokal yang memiliki cabang checkout lokal dan cabang jarak jauh
  3. git push / path / ke / bare / repo + ref / remote / asal / : ref / head /
Senthil A Kumar
sumber
0

Saya menggunakan skrip berikut untuk membaca file teks yang memiliki daftar semua repos SVN saya dan mengonversinya menjadi GIT, dan kemudian menggunakan git clone --bare untuk mengkonversi ke repo telanjang git

#!/bin/bash
file="list.txt"
while IFS= read -r repo_name
do
 printf '%s\n' "$repo_name"
 sudo git svn clone --shared --preserve-empty-dirs --authors-file=users.txt file:///programs/svn/$repo_name 
 sudo git clone --bare /programs/git/$repo_name $repo_name.git
 sudo chown -R www-data:www-data $repo_name.git
 sudo rm -rf $repo_name
done <"$file"

list.txt memiliki format

repo1_name
repo2_name

dan users.txt memiliki format

(no author) = Prince Rogers <[email protected]>

www-data adalah pengguna server web Apache, diperlukan izin untuk mendorong perubahan melalui HTTP

Pedro Vicente
sumber
0

Berikut adalah definisi dari repositori telanjang dari gitglossary :

Repositori kosong biasanya adalah direktori yang dinamai sesuai dengan akhiran .git yang tidak memiliki salinan check-out lokal dari salah satu file di bawah kontrol revisi. Yaitu, semua file administrasi dan kontrol Git yang biasanya ada di sub-direktori tersembunyi .git secara langsung hadir di direktori repository.git, dan tidak ada file lain yang hadir dan diperiksa. Biasanya penerbit repositori publik menyediakan repositori kosong.

Saya tiba di sini karena saya bermain-main dengan "repositori lokal" dan ingin dapat melakukan apa pun yang saya inginkan seolah-olah itu adalah repositori jarak jauh. Saya hanya bermain-main, mencoba belajar tentang git. Saya akan berasumsi bahwa ini adalah situasi bagi siapa pun yang ingin membaca jawaban ini.

Saya akan senang untuk pendapat ahli atau beberapa contoh-counter khusus, namun tampaknya (setelah mencari-cari beberapa kode sumber git yang saya temukan) hanya pergi ke file .git/configdan menetapkan atribut inti telanjang menjadi benar , git akan membiarkan Anda melakukan apa pun Anda ingin melakukan repositori dari jarak jauh. Yaitu baris berikut harus ada di .git/config:

[core]
    ...
    bare = true
...

(Ini kira-kira apa yang git config --bool core.bare trueakan dilakukan perintah , yang mungkin direkomendasikan untuk menghadapi situasi yang lebih rumit)

Pembenaran saya untuk klaim ini adalah bahwa, dalam kode sumber git, tampaknya ada dua cara berbeda untuk menguji apakah repo kosong atau tidak. Salah satunya adalah dengan memeriksa variabel global is_bare_repository_cfg. Ini diatur selama beberapa tahap persiapan eksekusi, dan mencerminkan nilai yang ditemukan dalam .git/configfile. Yang lainnya adalah fungsi is_bare_repository(). Berikut adalah definisi fungsi ini:

int is_bare_repository(void)
{
    /* if core.bare is not 'false', let's see if there is a work tree */
    return is_bare_repository_cfg && !get_git_work_tree();
} 

Aku sudah tidak memiliki waktu atau keahlian untuk mengatakan ini dengan keyakinan mutlak, tetapi sejauh yang saya tahu jika Anda memiliki bareatribut set ke truedalam .git/config, ini harus selalu kembali 1. Fungsi lainnya mungkin untuk situasi berikut:

  1. core.bare tidak terdefinisi (yaitu tidak benar atau salah)
  2. Tidak ada worktree (yaitu subdirektori .git adalah direktori utama)

Saya akan bereksperimen dengan itu ketika saya nanti, tetapi ini akan menunjukkan bahwa pengaturan core.bare = true sama dengan menghapus core.bare dari file konfigurasi dan mengatur direktori dengan benar.

Bagaimanapun, pengaturan core.bare = true tentu akan memungkinkan Anda mendorongnya, tapi saya tidak yakin apakah kehadiran file proyek akan menyebabkan beberapa operasi lain menjadi serba salah. Ini menarik dan saya kira instruktif untuk mendorong ke repositori dan melihat apa yang terjadi secara lokal (yaitu menjalankan git statusdan memahami hasilnya).

Nathan Chappell
sumber
-1

Pertama, backuprepo Anda yang ada:

(a)  mkdir backup

(b)  cd backup

(c)  git clone non_bare_repo

Kedua, jalankan yang berikut:

git clone --bare -l non_bare_repo new_bare_repo
Shaks
sumber
Untuk apa klon perantara?
Stabledog
-4

Oneliner untuk melakukan semua operasi di atas:

for i in `ls -A .`; do if [ $i != ".git" ]; then rm -rf $i; fi; done; mv .git/* .; rm -rf .git; git config --bool core.bare true

(jangan salahkan saya jika sesuatu meledak dan Anda tidak memiliki cadangan: P)

Tarmo
sumber
-9

Wow, sungguh menakjubkan berapa banyak orang yang ikut serta dalam hal ini, terutama mengingat sepertinya tidak ada seorang pun yang berhenti untuk bertanya mengapa orang ini melakukan apa yang dia lakukan.

Perbedaan HANYA antara repositori telanjang dan non-telanjang adalah bahwa versi non-telanjang memiliki salinan yang berfungsi. Alasan utama Anda memerlukan repo telanjang adalah jika Anda ingin membuatnya tersedia untuk pihak ketiga, Anda tidak dapat benar-benar mengerjakannya secara langsung sehingga pada titik tertentu Anda harus mengkloningnya pada titik mana Anda berada segera kembali ke versi copy pekerjaan biasa.

Yang sedang berkata, untuk mengkonversi ke repo telanjang yang harus Anda lakukan adalah memastikan Anda tidak memiliki komitmen tertunda dan kemudian hanya:

rm -R * && mv .git/* . && rm -R .git

Itu dia, repo telanjang.

Justin Buser
sumber
11
Ini tidak akan membuatnya cukup telanjang. Coba dorong ke dalamnya. Anda perlu melakukannya git config core.bare truejuga.
Antony Hatchkins
Saya tidak downvote, tapi saya hanya ingin menunjukkan bahwa bagian pertama dari jawaban ini yang menjelaskan mengapa Anda ingin repo telanjang vs yang non-telanjang ok , meskipun tidak mengandung detail teknis yang cukup, dan mungkin menjadi sedikit tidak akurat. Namun , untuk bagian ke-2 dari jawaban Anda, sementara perintah-perintah itu membuat repo Anda kosong, Anthony benar , Anda masih perlu mengatur git config core.bare true, seperti dalam jawaban ini .