Jak sklonować do niepustego katalogu?

572

Mam katalog A z plikami pasującymi do katalogu B. Katalog A może zawierać inne potrzebne pliki. Katalog B to repozytorium git.

Chcę sklonować katalog B do katalogu A, ale git-clone nie pozwoli mi na to, ponieważ katalog nie jest pusty.

Miałem nadzieję, że po prostu sklonuje .git, a ponieważ wszystkie pliki pasują, mogę stąd przejść?

Nie mogę sklonować do pustego katalogu, ponieważ mam pliki w katalogu A, których nie ma w katalogu B i chcę je zachować.

Kopiowanie .git nie jest opcją, ponieważ chcę, żeby referencje pchały / ciągnęły i nie chcę konfigurować ich ręcznie.

Czy jest na to sposób?

Aktualizacja: Myślę, że to działa, czy ktoś może zobaczyć jakieś problemy? ->

cd a
git clone --no-hardlinks --no-checkout ../b a.tmp 
mv a.tmp/.git .
rm -rf a.tmp
git unstage # apparently git thinks all the files are deleted if you don't do this
Dale Forester
źródło
5
może mógłbyś zmienić przyjętą odpowiedź?
Bastiaan Quast

Odpowiedzi:

724

To działało dla mnie:

git init
git remote add origin PATH/TO/REPO
git fetch
git reset origin/master  # Required when the versioned files existed in path before "git init" of this repo.
git checkout -t origin/master

UWAGA: -t ustawi dla ciebie odgałęzienie, jeśli tego właśnie chcesz, i zwykle tak jest.

cmcginty
źródło
70
Nie działa to w niepustym katalogu, gdy przychodzące pliki już istnieją (jak opisano w pierwotnym pytaniu). Ale jeśli git reset origin/masterpo tym git fetch, będzie działać (zachowując również wszelkie lokalne zmiany).
Araxia
8
fatal: Nie można zaktualizować ścieżek i jednocześnie przejść do gałęzi „master”.
Arnold Roa,
7
Ta odpowiedź nie działa dla mnie. Kiedy to robię, git checkout ...git skarży się, że wszystkie moje pliki zostaną nadpisane i powinienem je najpierw przenieść. Kiedy robię najpierw `git reset origin / master /`, polecenie kasowania skarży się, że gałąź o nazwie master już istnieje.
Saskia,
4
git checkout masterbył dla mnie wystarczającym ostatnim krokiem.
yoyo
16
Wszystkie etapy działało idealnie, ale ten ostatni dostał mnie: fatal: A branch named 'master' already exists. Myślę, że tak naprawdę tego nie potrzebowałem.
Shadi
164

W poniższych poleceniach powłoki existing-dirznajduje się katalog, którego zawartość jest zgodna ze śledzonymi plikami w plikurepo-to-clone repozytorium git.

# Clone just the repository's .git folder (excluding files as they are already in
# `existing-dir`) into an empty temporary directory
git clone --no-checkout repo-to-clone existing-dir/existing-dir.tmp # might want --no-hardlinks for cloning local repo

# Move the .git folder to the directory with the files.
# This makes `existing-dir` a git repo.
mv existing-dir/existing-dir.tmp/.git existing-dir/

# Delete the temporary directory
rmdir existing-dir/existing-dir.tmp
cd existing-dir

# git thinks all files are deleted, this reverts the state of the repo to HEAD.
# WARNING: any local changes to the files will be lost.
git reset --hard HEAD
Dale Forester
źródło
5
Musiałem to zrobić git reset --hard HEAD, inaczej nie zrezygnuje z „usuniętych” plików.
Dimitar
18
git reset HEADdziałało dobrze dla mnie. git reset --hard HEADniszczy wszelkie zmiany w plikach, więc jeśli nie są dokładnie takie same jak pliki w repozytorium, nie powinieneś tego robić.
Tgr
1
git reset HEADnie wydaje się mieć dla mnie żadnego wpływu. git reset --hard HEADrobi - ale powoduje to utratę wszelkich zmian wprowadzonych w plikach. Czy jest lepsze rozwiązanie?
Jacob Dorman
1
Odpowiedź Caseya - git init / remote add / fetch / checkout - jest czystsza i prostsza i nie wymaga żadnych folderów tymczasowych.
yoyo
1
@ Odpowiedź Casey nie działała dla mnie, gdy w folderach były już pliki, które musiały pozostać, ale nie były w repozytorium git. Jest to przydatne do aktualizowania konfiguracji po uruchomieniu skryptów instalacyjnych, w których tworzone są pliki i katalogi, ale należy zaktualizować / dodać pliki nad zainstalowanymi elementami.
soulston
104

Drobna modyfikacja jednej z odpowiedzi, która działała dla mnie:

git init
git remote add origin PATH/TO/REPO
git pull origin master

aby od razu rozpocząć pracę nad gałęzią master.

mohsaied
źródło
1
musiał zresetować HEAD - twardy, aby wyczyścić brudny istniejący katalog, bez usuwania niepotrzebnych plików określonych w gitignore
Ray Foss
1
Jest to ten, który faktycznie dla mnie zadziałał, w przeciwieństwie do odpowiedzi @ cmcginty.
pewno
4
Nie jest to do końca równoważne z git-clone - brakuje tylko informacji upstream dla gałęzi master. Można to naprawić, dodając git branch --set-upstream-to=origin/master master.
Slaven Rezic,
Ta wersja działała dla mnie, po prostu musiałem zresetować git - twardy HEAD
Frédéric Klee
29

Ostrzeżenie - może to potencjalnie zastąpić pliki.

git init     
git remote add origin PATH/TO/REPO     
git fetch     
git checkout -t origin/master -f

Zmodyfikowano z odpowiedzi @ cmcginty - bez opcji -f nie działało to dla mnie

JohnFF
źródło
Na pewno musisz po tym sprawdzić wszystkie pliki git checkout .?
Chris Stryczyński
25

Oto, co skończyłem, gdy miałem ten sam problem (przynajmniej myślę, że to ten sam problem). Wszedłem do katalogu A i pobiegłemgit init .

Ponieważ nie chciałem, aby po plikach w katalogu A pojawił się git, edytowałem .gitignore i dodałem do niego istniejące pliki. Po tym, jak uruchomiłem git remote add origin '<url>' && git pull origin masteret voíla, B zostaje „sklonowany” do A bez jednego czknięcia.

BjornSnoen
źródło
2
Ta technika nie działa w niepustym katalogu, gdy przychodzące pliki już istnieją (jak opisano w pierwotnym pytaniu).
Araxia
11

Użyłem tego kilka chwil temu, wymaga najmniej potencjalnie destrukcyjnych poleceń:

cd existing-dir
git clone --bare repo-to-clone .git
git config --unset core.bare
git remote rm origin
git remote add origin repo-to-clone
git reset

I voilá!

KuttKatrea
źródło
10

Kolejny prosty przepis wydaje mi się odpowiedni dla mnie:

git clone --bare $URL .git
git config core.bare false

Moim głównym przypadkiem użycia do wyewidencjonowania do katalogu z istniejącymi plikami jest kontrolowanie moich plików dotx z Uniksem za pomocą Git. Na nowym koncie katalog domowy będzie już zawierał niektóre pliki, być może nawet te, które chcę uzyskać z Git.

Ken Williams
źródło
1
Nagie repozytoria są konfigurowane nieco inaczej i chociaż to działa, nie polecam tego. :)
ThorSummoner,
1
Czy mógłbyś to sprecyzować? Co jest inne
Ken Williams
1
Tylko dwie różnice: 1.) .git/configPlik wskazuje, że repozytorium jest puste. 2.) Pliki normalnie przechowywane .gitsą przechowywane w katalogu głównym (który .git
nazwałeś
4
Są to dokładnie te zmiany, które do klonowania .giti ustawianie core.baresię falsezajmie, więc nadal czuć się dobrze o tej metodzie.
Ken Williams
10

To działało dla mnie:

cd existing_folder
git init
git remote add origin path_to_your_repo.git
git add .
git commit
git push -u origin master
Mike6679
źródło
6

Miałem podobny problem z nowym katalogiem internetowym Apache (konto utworzone w WHM), którego planowałem użyć jako tymczasowego serwera WWW. Musiałem początkowo sklonować mój nowy projekt z tamtejszą bazą kodu i okresowo wdrażać zmiany, wyciągając z repozytorium.

Problem polegał na tym, że konto zawierało już pliki serwera WWW, takie jak:

.bash_history
.bash_logout
.bash_profile
.bashrc
.contactemail
.cpanel/
...

... że nie chcę ani usuwać ani zatwierdzać mojego repozytorium. Potrzebowałem ich, aby pozostali tam bez sceny i bez śledzenia.

Co ja zrobiłem:

Poszedłem do mojego folderu internetowego (istniejący_folder):

cd /home/existing_folder

i wtedy:

git init
git remote add origin PATH/TO/REPO
git pull origin master
git status

Wyświetliła (zgodnie z oczekiwaniami) listę wielu plików, które nie były przemieszczane - te, które już istniały początkowo z mojego konta internetowego cPanel.

Następnie, dzięki temu artykułowi , właśnie dodałem listę tych plików do:

**.git/info/exclude**

Ten plik, podobnie jak .gitignoreplik, pozwala zignorować pliki przed przemieszczeniem. Po tym nie miałem nic do zatwierdzenia w katalogu .git / - działa jak osobisty.gitignore którego nikt inny nie widzi.

Teraz sprawdzanie git statuszwrotów:

On branch master
nothing to commit, working tree clean

Teraz mogę wdrożyć zmiany na tym serwerze WWW, po prostu pobierając z mojego repozytorium git. Mam nadzieję, że pomoże to niektórym twórcom stron internetowych łatwo stworzyć serwer pomostowy.

Vlado
źródło
5

Oto co robię:

git clone repo /tmp/folder
cp -rf /tmp/folder/.git /dest/folder/
cd /dest/folder
git checkout -f master
Philip Kirkbride
źródło
4

Może źle zrozumiałem twoje pytanie, ale czy nie byłoby łatwiej, jeśli skopiujesz / przeniesiesz pliki z A do git repo B i dodasz potrzebne za pomocą git add ?

AKTUALIZACJA: Z git doc:

Klonowanie do istniejącego katalogu jest dozwolone tylko wtedy, gdy katalog jest pusty.

ŹRÓDŁO: http://git-scm.com/docs/git-clone

Roberto Aloi
źródło
2
Nie, właściciel i pliki mogą być dowolne. Dotyczy to sytuacji wielu programistów. Wszyscy mamy istniejące katalogi i tylko jeden ma obecnie kasę git. Wszyscy w dużej mierze mamy ten sam podzbiór plików, więc chcemy, aby inni programiści mogli klonować, zachowując swoje pliki. I powinno być tak eleganckie i wygodne, jak to możliwe.
Dale Forester,
Szczerze mówiąc, nie widzę sensu rozwijania się w takim stanie. Nie możesz używać oddziałów i scalać operacji? Czy posiadanie sub-repozytoriów z zewnętrznymi zależnościami? Dlaczego miałbyś polegać na pojedynczym „kasie git”?
Roberto Aloi,
5
„Zamówienie pojedynczego gita” nie jest celem całej próby. Tyle, że tak już jest i potrzebujemy sposobu, aby iść naprzód. Zaktualizowałem oryginalne pytanie o rozwiązanie, które wydaje się działać. Doceniam jednak opinie.
Dale Forester
3
Istnieje wiele uzasadnionych przypadków - mam złożone drzewo folderów, które należy skonfigurować PRZED skonfigurowaniem źródła mojego projektu, a to drzewo folderów zawiera licencjonowane prace, których nie można na przykład przechowywać w GitHub.
BrainSlugs83,
3

Szukałem czegoś podobnego i oto, co wymyśliłem:

Moja sytuacja dotyczy sytuacji, w której mam aktywne drzewo sieciowe i próbowałem utworzyć dla niego zdalne repozytorium bez przenoszenia jakichkolwiek plików w bieżącym drzewie internetowym. Oto co zrobiłem:

  1. Przejdź do drzewa i uruchom git init
  2. Przejdź do zamierzonej lokalizacji repozytorium i uruchom: git clone --bare /path/to/web/repo
  3. Edytuj plik konfiguracyjny w moim zdalnym repozytorium i usuń [remote "origin"]sekcję.
  4. Dodaj [remote "origin"]sekcję do .git / config w drzewie sieci, wskazując na nowe zdalne repozytorium.
Lendrick
źródło
Bardzo podoba mi się ten przepis.
dland
git clone --bareTutaj jest zbędne i okrężną. Dlaczego nie po git remote add origin <URL>pierwsze?
Araxia
3

to działa dla mnie, ale powinieneś połączyć pliki repozytorium zdalnego z plikami lokalnymi:

git init
git remote add origin url-to-git
git branch --set-upstream-to=origin/master master
git fetch
git status
RODNEY ZHANG
źródło
1

Podobała mi się odpowiedź Dale'a , a także dodałem

git clone --depth 2 --no-checkout repo-to-clone existing-dir/existing-dir.tmp
git branch dev_new214
git checkout dev_new214
git add .
git commit
git checkout dev
git merge dev_new214

Płytka głębokość pozwoliła uniknąć wielu dodatkowych wczesnych zobowiązań deweloperów. Nowa gałąź dała nam dobrą wizualną historię, że został wstawiony nowy kod z tego serwera. To moim zdaniem idealne gałęzie. Moje podziękowania za świetny wgląd wszystkich ludzi, którzy tutaj pisali.

Dmitri R117
źródło
0

Te same problemy występowały podczas próby sklonowania do kodu c /

Ale ten folder zawiera całą masę projektów.

Utworzyłem nowy folder w c / code / newproject i zmapowałem klon do tego folderu.

git na pulpit następnie zapytał mojego użytkownika, a następnie sklonował dobrze.

Tomek
źródło