Jak przekonwertować normalne repozytorium Git na zwykłe?

602

Jak przekonwertować „normalne” repozytorium Git na zwykłe?

Główną różnicą wydaje się być:

  • w normalnym repozytorium Git w .gitfolderze znajduje się folder zawierający wszystkie istotne dane i wszystkie inne pliki tworzące kopię roboczą

  • w czystym repozytorium Git nie ma kopii roboczej, a folder (nazwijmy go repo.git) zawiera rzeczywiste dane repozytorium

Boldewyn
źródło
16
Prawdopodobnie jest to krótsza metoda:mv repo/.git repo.git; rm -rf repo
jameshfisher
Tak, prawda. Kiedy napisałem pytanie, to był tylko fragment mojej historii, który wykonałem w innym momencie.
Boldewyn
54
@eegg Użyj &&zamiast ;w przypadku mvniepowodzenia!

Odpowiedzi:

609

W skrócie: zamień zawartość repona zawartość repo/.git, a następnie powiedz repozytorium, że jest to już samo repozytorium.

Aby to zrobić, wykonaj następujące polecenia:

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

Pamiętaj, że różni się to od robienia git clone --barenowej lokalizacji (patrz poniżej).

Jörg W Mittag
źródło
9
Dzięki za podpowiedź na core.bare. Teraz, po przejrzeniu tej opcji, mogę to potwierdzić: kernel.org/pub/software/scm/git-core/docs/git-config.html
Boldewyn
14
Dziękuję Ci! Wydaje mi się to czystsze: mv repo / .git repo.git && rm -rf repo && cd repo.git && git config --bool core.bare true
JasonWoof
56
Jest to o wiele bardziej skomplikowane i kruche niż odpowiedź poniżej ( git clone --bare /path/to/repo).
djd
7
To rmpolecenie może wymagać * \.[!.]*raczej niż *usunięcia plików-kropek i katalogów-kropek.
minopret
6
@Ciantic: Ponownie, jak już wyjaśniłem w moim komentarzu powyżej, moja odpowiedź została udzielona 3 lata temu, ale 5 miesięcy temu ktoś zmienił pytanie w coś zupełnie innego. Żadna z odpowiedzi na tej stronie sprawi żadnego już sensu. Ta sekwencja poleceń została skopiowana bezpośrednio z pytania, właśnie dodałem ostatnie dwa wiersze.
Jörg W Mittag
244

Twoja metoda wygląda, jakby działała; struktura plików nagiego repozytorium jest właśnie tym, co znajduje się w katalogu .git. Ale nie wiem, czy któryś z plików został faktycznie zmieniony, więc jeśli to się nie powiedzie, możesz to zrobić

git clone --bare /path/to/repo

Prawdopodobnie będziesz musiał to zrobić w innym katalogu, aby uniknąć konfliktu nazw, a następnie możesz po prostu przenieść go z powrotem w wybrane miejsce. Konieczna może być zmiana pliku konfiguracyjnego, aby wskazywał gdziekolwiek znajduje się repozytorium oryginału.

jonescb
źródło
50
Źle, ta metoda nie jest równoważna. Wykonanie klonowania nie zachowuje opcji konfiguracji, które mogą mieć krytyczne znaczenie dla poprawnego działania, na przykład w przypadku korzystania z git-p4. Dodatkowo, klon niszczy piloty, ponownie z czymś takim jak git-p4 tracisz gałąź p4 / master podczas klonowania, więc powyższe podejście jest lepsze.
nosatalian
26
Ale możesz z łatwością przesłać opcje konfiguracji, kopiując odpowiednie części pliku konfiguracji. Nadal uważam tę metodę za czystszą niż ręczne kopiowanie i zmiana nazw plików.
Philipp
6
Jest to idealne po migracji subversion, ponieważ git-svn nie obsługuje --bare.
Keyo,
11
Aby uniknąć konfliktu nazw ---git clone --bare /path/to/repo.git /path/to/newbarerepo.git
raksja
Działa to tak długo, jak git update-server-infopo utworzeniu uruchomisz repozytorium.
ACK_stoverflow
116

Myślę, że poniższy link byłby pomocny

GitFaq: Jak sprawić, by istniejące repozytorium nie było puste?

$ mv repo/.git repo.git
$ git --git-dir=repo.git config core.bare true
$ rm -rf repo
xhh
źródło
2
Tak, właśnie tego szukałem, dzięki! Jednak ich druga propozycja ( git clone) ma wady wspomniane powyżej przez nosatalian.
Boldewyn,
1
Dokumentacja, którą zasugerowałeś, mówi dalej: „Bezpieczniejszą metodą jest pozwolenie Gitowi na obsługę wszystkich ustawień wewnętrznych, wykonując coś takiego: gon clone --bare -l <ścieżka_do_repos> <katalog_nowy>>
dafunker
74

O ile nie chcesz lub nie chcesz przekręcać bitów w systemie plików, naprawdę nie jest łatwo stworzyć nagą wersję nie-nagiego repozytorium (wspomnianego w kilku innych postach tutaj). Jest to część podstawowej funkcjonalności gita:

git clone --bare existing_repo_path bare_repo_path

Chip Kaye
źródło
6
Niesamowite, że najlepsza jak dotąd odpowiedź ma 0 głosów po> 4 miesiącach. Niezbyt dobra, ale niebezpieczna „zaakceptowana odpowiedź” ma 200!
Stabledog
36
Wcale nie niesamowite - ta odpowiedź nie robi tego, co zadało pierwotne pytanie. Nie konwertuje repozytorium, klonuje je, tracąc informacje w procesie (na przykład zdalne gałęzie).
GreenAsJade,
15

Proszę również rozważyć użycie

git clone --mirror path_to_source_repository

Z dokumentacji :

Skonfiguruj kopię lustrzaną repozytorium źródłowego. Oznacza to - zupełnie. W porównaniu do --bare, --mirror nie tylko mapuje lokalne gałęzie źródła do lokalnych gałęzi celu, ale także mapuje wszystkie referencje (w tym gałęzie zdalnego śledzenia, notatki itp.) I konfiguruje konfigurację referencji tak, aby wszystkie te referencje są zastępowane zdalną aktualizacją git w docelowym repozytorium.

Jacek Krawczyk
źródło
Wydaje się, że jest to najbardziej zwięzły, kompletny i bezpieczny sposób robienia tego, czego chce OP (a nie tylko clone). Czy coś brakuje? Czy był --mirrorto stosunkowo nowy dodatek?
Craig Silver
@CraigSilver: Nie, jak widzę w historii dokumentacji w takiej formie, --mirrorjest ona dostępna od wersji 1.7, więc już dość długo. Możesz sprawdzić tutaj
Jacek Krawczyk
7

Chciałem tylko wypchnąć repozytorium na ścieżce sieciowej, ale git nie pozwoli mi tego zrobić, chyba że to repozytorium zostanie oznaczone jako puste. Wszystko czego potrzebowałem to zmienić jego konfigurację:

git config --bool core.bare true

Nie musisz majstrować przy plikach, chyba że chcesz je utrzymać w czystości.

Slion
źródło
3
Jest to niebezpieczne, gdy chcesz również pracować nad drzewem pracy zdalnego repozytorium. Możliwe, że prędzej czy później cofniesz zmianę po prostu dlatego, że twoje drzewo pracy zdalnej i indeks nie były zsynchronizowane z repozytorium. Nie polecam tego rozwiązania, jeśli nie wiesz dokładnie , co robisz.
Boldewyn
To prawda, że ​​nie powinieneś pracować na drzewie zdalnego nagiego repozytorium.
Slion
6

przeczytałem odpowiedzi i zrobiłem to:

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

pozostawi to zawartość repos/.gitnagąrepos.git

Dan D.
źródło
4

Oto, co uważam za najbezpieczniejsze i najprostsze. Nic tu nie zostało powiedziane powyżej. Chcę tylko zobaczyć odpowiedź, która pokazuje bezpieczną procedurę krok po kroku. Zaczynasz jeden folder z repozytorium (repo), które chcesz odsłonić. Przyjąłem konwencję sugerowaną powyżej, że nagie foldery repozytoriów mają rozszerzenie .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
źródło
1
nie jest to o wiele bezpieczniejsze, ponieważ wykonałeś kopię zapasową za pomocą git clone. Tworzenie kopii zapasowej przez klonowanie spowoduje utratę niektórych konfiguracji, co w niektórych przypadkach może mieć kluczowe znaczenie dla repozytorium.
Lie Ryan,
Odnotowany. Jedyne konfiguracje, o które mi zawsze chodziło, są globalne dla wszystkich moich lokalnych repozytoriów.
sdesciencelover
4

Po prostu przeczytaj

Pro Git Book: 4.2 Git na serwerze - uzyskiwanie Git na serwerze

które boild do

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

Następnie umieść my_project.git na serwerze

Która głównie jest taka, na jaką próbę wskazała odpowiedź nr 42 . Z pewnością można by na nowo wymyślić koło ;-)

apos
źródło
Nie rozumiem, co dodaje ta odpowiedź, o czym nie rozmawialiśmy w żadnej innej odpowiedzi (w tym w głosowaniu negatywnym). Czy mógłbyś wyjaśnić? (Nawiasem mówiąc: Pro Git Book mówi „To jest mniej więcej odpowiednik czegoś takiego jak ...” , a ta dokładna równoważność jest już tutaj omawiana.)
Boldewyn
3

Oto mała funkcja BASH, którą możesz dodać do .bashrc lub .profile w systemie UNIX. Po dodaniu i powłoka jest albo restartowana, albo plik jest ładowany ponownie przez wywołanie do source ~/.profilelub 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
}

Po wywołaniu w katalogu zawierającym katalog .git dokona odpowiednich zmian w celu konwersji repozytorium. Jeśli po wywołaniu nie ma katalogu .git, pojawi się komunikat BŁĄD i nie nastąpi zmiana systemu plików.

Nyteshade
źródło
1

Metody, które mówią o usuwaniu plików i grzebaniu przy przenoszeniu katalogu .git, nie są czyste i nie używają metody „git” do robienia czegoś, co powinno być proste. To najczystsza metoda, jaką znalazłem, aby przekonwertować normalne repo na zwykłe repo.

Najpierw klon / path / to / normal / repo do samego repo o nazwie repo.git

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

Następnie usuń początek wskazujący na / path / to / normal / repo

cd repo.git
git remote rm origin

Wreszcie możesz usunąć swoje oryginalne repozytorium. W tym momencie możesz zmienić nazwę repo.git, aby repo, ale standardowa konwencja oznaczająca repozytorium git to coś.git, więc osobiście zostawiłbym to w ten sposób.

Po wykonaniu tego wszystkiego możesz sklonować swoje nowe repozytorium (co w efekcie tworzy normalne repo, a także sposób, w jaki przekształcisz go z wersji zwykłej na normalną)

Oczywiście, jeśli masz inne upstamy, zechcesz je zanotować i zaktualizować swoje repozytorium, aby je uwzględnić. Ale znowu wszystko można zrobić za pomocą polecenia git. Pamiętaj, że strony podręcznika man są twoim przyjacielem.

krux
źródło
1
Czy próbowałeś przeczytać inne odpowiedzi? Zwłaszcza komentarz @ jonescb i @ nosatalian do tego? Metoda „git” jest następująca: „Rób jak najwięcej z zwykłymi plikami tekstowymi”. Powinieneś zacząć sprawdzać wewnętrzne elementy .gitfolderu. Bardzo pouczające jest nauczenie się, jak pasują do siebie części.
Boldewyn
1

Jeśli masz repozytorium z kilkoma lokalnymi oddziałami do kasy / refs / heads / * i kilkoma zdalnymi oddziałami pilotów / origin / * ORAZ jeśli chcesz przekonwertować to na BARE repozytorium ze wszystkimi oddziałami w / refs / heads / *

możesz wykonać następujące czynności, aby zapisać historię.

  1. utworzyć puste repozytorium
  2. cd do lokalnego repozytorium, które ma lokalne oddziały kasy i oddziały zdalne
  3. git push / path / to / bare / repo + refs / remotes / origin / : refs / heads /
Senthil A Kumar
źródło
0

Użyłem następującego skryptu, aby odczytać plik tekstowy z listą wszystkich moich repozytoriów SVN i przekonwertować je na GIT, a następnie użyć git clone --bare, aby przekonwertować na zwykłe repozytorium 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 ma format

repo1_name
repo2_name

i users.txt ma format

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

www-data jest użytkownikiem serwera WWW Apache, potrzebne jest zezwolenie na przesyłanie zmian przez HTTP

Pedro Vicente
źródło
0

Oto definicja nagiego repozytorium z gitglossary :

Samo repozytorium jest zwykle odpowiednio nazwanym katalogiem z sufiksem .git, który nie ma pobranej lokalnie kopii żadnego z plików znajdujących się pod kontrolą wersji. Oznacza to, że wszystkie pliki administracyjne i kontrolne Git, które normalnie byłyby obecne w ukrytym podkatalogu .git, są bezpośrednio obecne w katalogu repository.git, a żadne inne pliki nie są obecne i wyewidencjonowane. Zwykle wydawcy repozytoriów publicznych udostępniają repozytoria nagie.

Przybyłem tutaj, ponieważ bawiłem się „lokalnym repozytorium” i chciałem móc robić wszystko, co chciałem, tak jakby to było zdalne repozytorium. Po prostu się bawiłem, próbując dowiedzieć się o git. Zakładam, że taka jest sytuacja każdego, kto chce przeczytać tę odpowiedź.

Chciałbym na opinii biegłego lub kilku konkretnych przykłady przeciwne, jednak wydaje się, że (po grzebać jakiegoś kodu źródłowego git że znalazłem) po prostu przechodząc do pliku .git/configi ustawienie rdzeń atrybut urodziła się prawdą , git pozwoli Ci zrobić cokolwiek chcesz zrobić zdalnie z repozytorium. To znaczy, następujące linie powinny istnieć w .git/config:

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

(To jest mniej więcej to polecenie git config --bool core.bare true zrobi to , co prawdopodobnie zaleca się w przypadku bardziej skomplikowanych sytuacji)

Moim uzasadnieniem dla tego twierdzenia jest to, że w kodzie źródłowym git wydaje się, że istnieją dwa różne sposoby testowania, czy repo jest czyste, czy nie. Jednym z nich jest sprawdzenie zmiennej globalnej is_bare_repository_cfg. Jest to ustawiane podczas pewnej fazy instalacji i odzwierciedla wartość znalezioną w .git/configpliku. Drugi jest funkcją is_bare_repository(). Oto definicja tej funkcji:

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();
} 

Ja nie mam czasu ani wiedzy, aby to powiedzieć z absolutną pewnością, ale o ile mogę powiedzieć, jeśli masz barezestaw przypisywać truew .git/configten zawsze powinien wrócić 1. Reszta funkcji prawdopodobnie dotyczy następującej sytuacji:

  1. core.bare jest niezdefiniowany (tj. ani prawda, ani fałsz)
  2. Nie ma drzewa roboczego (tzn. Podkatalog .git jest katalogiem głównym)

Eksperymentuję z tym, kiedy będę mógł później, ale wydaje się to wskazywać, że ustawienie core.bare = true jest równoważne z usunięciem core.bare z pliku konfiguracyjnego i prawidłowym skonfigurowaniem katalogów.

W każdym razie ustawienie core.bare = true z pewnością pozwoli ci to zrobić, ale nie jestem pewien, czy obecność plików projektu spowoduje, że niektóre inne operacje nie będą działać poprawnie. Jest to interesujące i przypuszczam, że pouczające jest pchanie do repozytorium i sprawdzanie, co się stało lokalnie (tj. Uruchamianie i sprawdzanie git statuswyników).

Nathan Chappell
źródło
-1

Po pierwsze, backuptwoje istniejące repozytorium:

(a)  mkdir backup

(b)  cd backup

(c)  git clone non_bare_repo

Po drugie, uruchom następujące polecenie:

git clone --bare -l non_bare_repo new_bare_repo
Shaks
źródło
Do czego służy pośredni klon?
Stabledog
-4

Oneliner do wykonywania wszystkich powyższych operacji:

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

(nie obwiniaj mnie, jeśli coś wybuchnie i nie masz kopii zapasowych: P)

Tarmo
źródło
-9

Wow, to po prostu niesamowite, ile osób się w to włączyło, szczególnie biorąc pod uwagę, że nie wydaje się, aby nikt nie przestał pytać, dlaczego ta osoba robi to, co robi.

Jedyną różnicą między zwykłym repozytorium git a tym, co nie, jest to, że wersja nienazywana ma kopię roboczą. Głównym powodem, dla którego potrzebujesz nagiego repozytorium, jest to, że jeśli chcesz udostępnić go innej osobie, nie możesz bezpośrednio nad nim pracować, więc w pewnym momencie będziesz musiał go sklonować. wróć do zwykłej wersji roboczej.

Biorąc to pod uwagę, aby przejść do zwykłego repozytorium, wystarczy upewnić się, że nie ma żadnych oczekujących zmian, a następnie:

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

Proszę bardzo, repo.

Justin Buser
źródło
11
To nie sprawi, że będzie wystarczająco naga. Spróbuj wepchnąć się w to. Ty też musisz to zrobić git config core.bare true.
Antony Hatchkins
Nie przegłosowałem, ale chciałem tylko zaznaczyć, że pierwsza część tej odpowiedzi, która wyjaśnia, dlaczego chcesz mieć nagie repo w porównaniu z repozytorium non-go, jest w porządku , chociaż nie zawiera wystarczającej liczby szczegółów technicznych i może być nieco niedokładnym. Jednak jeśli chodzi o drugą część twojej odpowiedzi, chociaż te polecenia powodują, że twoje repozytorium jest puste, Anthony ma rację , wciąż musisz ustawić git config core.bare true, tak jak w tej odpowiedzi .