Jaka jest najlepsza praktyka „klonowania gita” w istniejącym folderze?

479

Mam kopię roboczą projektu, bez metadanych kontroli źródła. Teraz chciałbym zrobić odpowiednik git-clone w tym folderze i zachować moje lokalne zmiany.

git-clone nie pozwala mi klonować do istniejącego folderu. Jaka jest tutaj najlepsza praktyka?

ripper234
źródło
4
Lepsza dyskusja jest tutaj .
cdunn2001,
1
@MEM Podoba mi się ta odpowiedź bardziej, ale albo działa ... stackoverflow.com/a/5377989/11236
ripper234
2
@ ripper234 - Tak. Byłem w tej samej sytuacji i po prostu zrobiłem te kroki i żadnych problemów. Wszystko czyste i miłe. Wydaje mi się, że to kwestia preferencji. Najważniejsze jest to, że oba działają, jak twierdzisz. Twoje zdrowie.
MEM
1
Jest to tak szalone, że nie ma czystego sposobu na osiągnięcie tego, tak przydatnego, gdy chcesz sklonować projekt do zamontowanego folderu współdzielonego.
Thomas Decaux,
1
Możliwy duplikat Jak sklonować w niepustym katalogu?
Tobias Kienzler,

Odpowiedzi:

557

Można to zrobić poprzez klonowanie do nowego katalogu, a następnie przeniesienie .gitkatalogu do istniejącego katalogu.

Jeśli twój istniejący katalog nosi nazwę „kod”.

git clone https://myrepo.com/git.git temp
mv temp/.git code/.git
rm -rf temp

Można to również zrobić bez robienia kasy podczas polecenia klonowania; więcej informacji można znaleźć tutaj .

amicitas
źródło
25
Zauważ, że jest to dokładnie sugestia @ChrisJohnsen pozostawiona w komentarzach. Uznałem, że jest to przydatne i chciałem zrobić z niego prawdziwą odpowiedź. Chris, jeśli w końcu znajdziesz odpowiedź, chętnie ją usunę.
amicitas,
2
Dzięki! Chociaż brakuje w tym kroku „git Checkout -”. ponieważ uważa, że ​​wszystkie pliki zostały usunięte, prawda?
mrooney,
2
Nie, dopóki użyjesz git clonejako pierwszego polecenia, dalsze polecenie pobierania nie jest konieczne. Jeśli zamiast tego użyjesz czegoś takiego jak git clone --no-checkoutw pierwszym kroku, po przeniesieniu katalogu .git konieczne będzie użycie git reset HEADpolecenia poinformowania gita, że ​​pliki nie zostały usunięte.
amicitas
3
Dodałbym to jako trzeci krok: mv temp / .gitignore code / .gitignore
Daniel Aranda
1
@KalpeshSoni, tak git będzie wiedział o zmodyfikowanych plikach i będzie można zobaczyć zmiany za pomocą normalnych poleceń git, takich jak git status.
amicitas
284

Nie klonuj, pobierz zamiast. W repozytorium:

git init
git remote add origin $url_of_clone_source
git fetch origin
git checkout -b master --track origin/master # origin/master is clone's default

Następnie możesz zresetować drzewo, aby uzyskać żądane zatwierdzenie:

git reset origin/master # or whatever commit you think is proper...

i jesteś jak sklonowany.

Interesujące pytanie tutaj (i jedno bez odpowiedzi): jak dowiedzieć się, na którym podstawie opierało się twoje nagie drzewo, a zatem na której pozycji zresetować.

Andreas Krey
źródło
7
Nie jestem fanem tego - według konfiguracji github „Wskazówka: Pomocnik poświadczeń działa tylko po sklonowaniu adresu URL repozytorium HTTPS”. Używałem pomocnika uwierzytelnienia, co posłało mnie do długiej, dość bezowocnej nory królika.
Andrew
5
„git checkout --track origin / master” również działa dobrze zamiast „git checkout -b master --track origin / master”. Reset nie jest potrzebny.
felipecrp
1
Pojawił się błąd „Błąd Git: Następujące nieśledzone działające pliki drzewa zostaną nadpisane przez kasę”, więc dodaję to polecenie: git clean -d -fx "”
shakaran
1
zdecydowanie nie wskazane we wszystkich sytuacjach, ale właśnie tego potrzebowałem.
Chaim Eliyah
1
@AndreasKrey Twoja oryginalna odpowiedź (którą przeszedłem do historii edycji) zawiera dokładnie to, czego potrzebuje pytanie (i ja). Zmienione paski odpowiedzi przy kasie bez użycia opcji -f, która odrzuca lokalne zmiany i jest dokładnie tym, czego nie chcę. Gdybym był tobą, rozważyłbym przywrócenie oryginalnej odpowiedzi.
Ajean
77

Wykonałem następujące czynności, aby dokonać transakcji oddziału master w istniejącym katalogu:

git init
git remote add origin [my-repo]
git fetch
git checkout origin/master -ft
alexwenzel
źródło
2
To świetna odpowiedź i pozwala uniknąć finansowania systemu plików.
user151841
1
To powinna być zaakceptowana odpowiedź, ponieważ nie jest to hack.
php_nub_qq
5
W rzeczywistości robi to dokładnie to, czego OP (i ja) nie chcą, czyli zastąpienie lokalnych zmian.
Ajean
Mój głos mówi, że to pomogło MNIE, ale nie jest to najlepsza odpowiedź na pytanie PO.
TecBrat,
2
Czy ktoś może wyjaśnić, dlaczego -tużyto tu flagi?
jfowkes
38

Przejdę git clonedo nowego katalogu i skopiuję zawartość istniejącego katalogu do nowego klonu.

jhwist
źródło
4
jeśli to zrobisz, upewnij się, że dokładnie sprawdziłeś różnicę przed zatwierdzeniem - jest to absolutnie klasyczny przypadek, w którym możesz przypadkowo przywrócić zmiany wprowadzone w repozytorium źródłowym od czasu otrzymania kopii roboczej - ponieważ nie ma wystarczających informacji w kopii roboczej, aby dowiedzieć się, jakie zmiany wprowadziłeś, a jak to było przed rozpoczęciem wprowadzania zmian, aby połączyć się z innymi zmianami wprowadzonymi w repozytorium. Widziałem to wielokrotnie w tej sytuacji, do tego stopnia, że ​​„mocno zniechęcałem” siebie i ludzi, z którymi współpracowałem, od zrobienia tego.
Ben Clifford
72
git clone wherever tmp && git mv tmp/.git . && rm -rf tmpInnymi słowy, przeniesienie katalogu .gitpoza tymczasowy klon wydaje się prostsze niż wyczyszczenie działającego drzewa klonowania i skopiowanie tam istniejących plików.
Chris Johnsen
1
@ChrisJohnsen: powinieneś był znaleźć odpowiedź, to zdecydowanie najlepszy sposób, aby to zrobić imho
Stefano
2
@ChrisJohnsen git mv tmp/.git .wraca fatal: cannot move directory over file, source=tmp/.git, destination=.gitpo mnie. Czy ktoś wie, na czym polega problem?
Dennis,
6
@Dennis, To literówka: to polecenie powinno być proste mv, a nie git mv; chociaż to nie wyjaśnia, dlaczego masz .gitjuż plik (zawierający gitdir: some/path/to/a/git-dir„gitfile”; gdyby go nie było, zobaczyłbyś fatal: Not a git repository (or any of the parent directories): .gitzamiast tego).
Chris Johnsen,
34

Korzystanie z katalogu tymczasowego jest w porządku, ale zadziała, jeśli chcesz uniknąć tego kroku. Z katalogu głównego katalogu roboczego:

$ rm -fr .git
$ git init
$ git remote add origin your-git-url
$ git fetch
$ git reset --mixed origin/master
użytkownik1055643
źródło
20
git reset --hard origin/masterusunie wszystkie lokalne pliki.
Mouad Debbar
1
aby dodać do tego, co już wskazano powyżej, różnica między hardi mixedpolega na tym, że mieszane zachowa zmiany lokalne (więc jeśli spróbujesz później go wyciągnąć, pokaże Ci np. Nie można wyciągnąć z rebase: masz zmiany niestabilne. Zatwierdź je lub ukryj ) , podczas gdy twardy odrzuci te lokalne zmiany
aexl
Źle napisałeś pilota.
Glenn Dayton
10
git clone your_repo tmp && mv tmp/.git . && rm -rf tmp && git reset --mixed
return1.at
źródło
7
Użycie git reset --hardspowoduje zmianę lokalnych plików, szczególnie NIE o to poprosił ten OP. --mixednależy zamiast tego użyć.
Caleb
4

Aby sklonować repozytorium git w pustym istniejącym katalogu, wykonaj następujące czynności:

cd myfolder
git clone https://myrepo.com/git.git . 

Zwróć uwagę .na koniec git clonepolecenia. Spowoduje to pobranie repozytorium do bieżącego katalogu roboczego.

dobrze, mów
źródło
4
fatal: destination path '.' already exists and is not an empty directory.
Roland Kofler,
Katalog musi być pusty.
okTalk
4
OP prosi o klonowanie w istniejącym projekcie, stwierdzając, że klon git narzeka. Zła odpowiedź.
mix3d
Działa to tylko podczas tworzenia nowego katalogu, uruchamiania powyższych poleceń bez użycia „git init”
Bilal Ahmed
3

Wiele odpowiedzi już na to, tak jak chciał PO. Warto jednak zauważyć, że robienie tego w drugą stronę jest znacznie prostsze:

git clone repo-url tmp/
cp -R working/ tmp/

Masz teraz pożądany stan docelowy - świeży klon + lokalne zmiany.

Andrzej
źródło
2

Istnieją dwa podejścia do tego. Jeśli to możliwe, zacznę od czystego folderu dla nowego katalogu roboczego git, a następnie skopiuję twoją wersję rzeczy później. Może to wyglądać jak *:

mv $dir $dir.orig
git clone $url $dir
rsync -av --delete --exclude '.git' $dir.orig/ $dir/
rm -rf $dir.orig

W tym momencie powinieneś mieć całkiem czystą kopię roboczą z poprzednim folderem roboczym jako bieżącym katalogiem roboczym, więc wszelkie zmiany obejmujące usunięcie plików pojawią się na radarze, jeśli uruchomisz git status.

Z drugiej strony, jeśli naprawdę musisz to zrobić na odwrót, możesz uzyskać ten sam wynik z czymś takim:

cd $dir
git clone --no-checkout $url tempdir
mv tempdir/.git .
rmdir tempdir
git reset --mixed HEAD

Tak czy inaczej, pierwszą rzeczą, którą chciałbym zrobić, to uruchomić coś takiego, git stashaby uzyskać kopię wszystkich lokalnych zmian odłożonych na bok, a następnie możesz je ponownie zastosować i przeanalizować, które z nich chcesz popełnić.

* Oba przykłady zakładają, że zaczynasz od powłoki w katalogu nadrzędnym swojego projektu.

Caleb
źródło
2

To najlepsza ze wszystkich metod, jakie spotkałem

Sklonuj tylko folder .git repozytorium (wyłączając pliki, które już są w folderze existing-dir) do pustego katalogu tymczasowego

  1. git clone --no-checkout repo-path-to-clone existing-dir/existing-dir.tmp // może chcieć --no-hardlinks do klonowania lokalnego repozytorium

Przenieś folder .git do katalogu z plikami. To sprawia, że existing-dirrepozytorium git.

  1. mv existing-dir/existing-dir.tmp/.git existing-dir/

Usuń katalog tymczasowy

  1. rmdir existing-dir/existing-dir.tmp

  2. cd existing-dir

Git uważa, że ​​wszystkie pliki zostały usunięte, co przywraca stan repozytorium do HEAD.

UWAGA: wszelkie lokalne zmiany w plikach zostaną utracone.

  1. git reset --mixed HEAD
Amirtha Rajan
źródło
1
Twardy reset wydaje się niepożądany w 99% przypadków, w których trzeba to zrobić.
Stefan Fabian
0

Jeśli używasz co najmniej git 1.7.7 (który nauczył się clonetej --configopcji), aby zmienić bieżący katalog w kopię roboczą:

git clone example.com/my.git ./.git --mirror --config core.bare=false

Działa to przez:

  • Klonowanie repozytorium w nowym .gitfolderze
  • --mirrorsprawia, że nowy klon w folderze jako czysto metadanych .gitmusi być
  • --config core.bare=falsecountermands niejawny bare=truez --mirroropcji, umożliwiając tym samym repozytorium mieć skojarzony katalog roboczy i działać jak normalny klonu

To oczywiście nie zadziała, jeśli .gitkatalog metadanych już istnieje w katalogu, który chcesz przekształcić w kopię roboczą.

ThorSummoner
źródło
1
Zauważ, że ta technika zaowocuje [core]sekcją konfiguracji lokalnej obejmującą zarówno bare = true i bare = false . Bardziej problematyczne jest to, że będzie miał niepoprawne wartości dla originpilota, wraz z [remote "origin"]sekcją zawierającą mirror = truespecyfikację pobierania, która nie będzie działać poprawnie z kopią roboczą. Po rozwiązaniu tych problemów klonowanie normalnie i przenoszenie nowych kopii roboczych .gitbędzie bardziej wydajne.
Araxia
0

Zwykle najpierw sklonuję pierwsze repozytorium, a następnie przeniosę wszystko z istniejącego folderu do początkowego repozytorium. Działa za każdym razem.

Zaletą tej metody jest to, że nie przegapisz niczego z początkowego repozytorium, w tym README lub .gitignore.

Możesz także użyć poniższego polecenia, aby zakończyć kroki:

$ git clone https://github.com/your_repo.git && mv existing_folder/* your_repo
Mike Chen
źródło
0

Możesz to zrobić, wpisując rekurencyjnie następujące wiersze poleceń:

mkdir temp_dir   //  Create new temporary dicetory named temp_dir
git clone https://www...........git temp_dir // Clone your git repo inside it
mv temp_dir/* existing_dir // Move the recently cloned repo content from the temp_dir to your existing_dir
rm -rf temp_dir // Remove the created temporary directory
MUSTAPHA GHLISSI
źródło
0

Po prostu użyj. na końcu git clonepolecenia (znajdującego się w tym katalogu), jak poniżej:

cd your_dir_to_clone_in/
git clone [email protected]/somerepo/ .
John F.
źródło