Как мне клонировать в непустую директорию?

573

У меня есть каталог A с файлами, совпадающими с каталогом B. В каталоге A могут быть другие необходимые файлы. Каталог B - это git-репо.

Я хочу клонировать каталог B в каталог A, но git-clone не разрешит мне, так как каталог не пустой.

Я надеялся, что он просто клонирует .git, и, поскольку все файлы совпадают, я могу перейти оттуда?

Я не могу клонировать в пустой каталог, потому что у меня есть файлы в каталоге A, которых нет в каталоге B, и я хочу их сохранить.

Копирование .git не вариант, так как я хочу, чтобы ссылки пушли / тянули, и я не хочу устанавливать их вручную.

Есть какой-либо способ сделать это?

Обновление: я думаю, что это работает, кто-нибудь может увидеть какие-либо проблемы? ->

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
Дейл Форестер
источник
5
возможно, вы могли бы изменить принятый ответ?
Бастиан Quast

Ответы:

724

Это сработало для меня:

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

ПРИМЕЧАНИЕ: -t установит ветку upstream для вас, если это то, что вы хотите, и обычно это так.

cmcginty
источник
70
Это не работает в непустом каталоге, когда входящие файлы уже существуют (как описывает оригинальный вопрос). Но если вы git reset origin/masterпосле git fetch, это будет работать (также сохраняя любые локальные изменения).
Араксия
8
Неустранимый: Невозможно обновить пути и переключиться на ветку 'master' одновременно.
Арнольд Роа
7
Этот ответ не работает для меня. Когда я делаю git checkout ...git, жалуется, что все мои файлы будут перезаписаны, и я должен сначала переместить их. Когда я сначала выполняю `git reset origin / master /`, команда checkout жалуется, что ветвь с именем master уже существует.
Саския
4
git checkout masterбыл достаточным последним шагом для меня.
йо
16
Все шаги работали отлично, но последний получил меня fatal: A branch named 'master' already exists. Я думаю, что мне это не нужно.
Шади
164

В следующих командах оболочки existing-dirесть каталог, содержимое которого соответствует отслеживаемым файлам в repo-to-cloneрепозитории 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
Дейл Форестер
источник
5
Мне нужно было сделать, git reset --hard HEADиначе он не отказался бы от «удаленных» файлов.
Димитар
18
git reset HEADработал нормально для меня. git reset --hard HEADуничтожает любые изменения в ваших файлах, поэтому, если они не совпадают с файлами в хранилище, вы не должны этого делать.
Tgr
1
git reset HEADкажется, не имеет никакого влияния на меня. git reset --hard HEADделает - но это теряет любые изменения, которые вы внесли в файлы. Есть ли лучшее решение?
Джейкоб Дорман
1
@ Ответ Кейси - git init / remote add / fetch / checkout - чище и проще и не требует никаких временных папок.
Йо
1
Ответ @ Кейси не сработал, когда в папках уже были файлы, которые нужно было сохранить, но их не было в git-репо. Это полезно для обновления конфигурации после запуска сценариев установки, где создаются файлы и каталоги, но вам нужно обновить / добавить файлы поверх установленных элементов.
соулстон
104

Небольшая модификация одного из ответов, который работал для меня:

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

начать работу над мастер-веткой прямо сейчас.

mohsaied
источник
1
пришлось сделать сброс HEAD --hard, чтобы очистить грязный существующий каталог, не удаляя ненужные файлы, указанные в gitignore
Ray Foss
1
Это тот, который действительно работал для меня, в отличие от ответа @ cmcginty.
конечно же,
4
Это не совсем эквивалентно git-клону - отсутствует информация об исходной ветке master. Это можно исправить, добавив git branch --set-upstream-to=origin/master master.
Slaven Rezic
Эта версия работала для меня, просто пришлось сделать git reset --hard HEAD
Frédéric Klee
30

Предупреждение - это может перезаписать файлы.

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

Модифицировано из ответа @ cmcginty - без -f у меня не получилось

JohnFF
источник
Конечно, вам нужно проверить все файлы после этого с git checkout .?
Крис Стричински
25

Вот что я в итоге делал, когда у меня была та же проблема (по крайней мере, я думаю, что это та же проблема). Я пошел в каталог А и побежалgit init .

Поскольку я не хотел, чтобы за файлами в каталоге A следовал git, я отредактировал .gitignore и добавил в него существующие файлы. После этого я побежал git remote add origin '<url>' && git pull origin masterи вуаля, B «клонируется» в A без единого сбоя.

BjornSnoen
источник
2
Этот метод не работает в непустом каталоге, когда входящие файлы уже существуют (как описывает оригинальный вопрос).
Араксия
11

Я использовал это несколько минут назад, требуя наименее потенциально разрушительных команд:

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

И вуаля!

KuttKatrea
источник
10

Другой простой рецепт, кажется, хорошо работает для меня:

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

Мой основной вариант использования для извлечения в каталог с существующими файлами - это управление моими точечными файлами Unix с помощью Git. В новой учетной записи в домашнем каталоге уже будут некоторые файлы, возможно, даже те, которые я хочу получить из Git.

Кен Уильямс
источник
1
Голые репозитории настроены немного по-другому, и хотя это работает, я бы не советовал. :)
ThorSummoner
1
Можете быть более конкретными? Какая разница?
Кен Уильямс
1
Только два отличия: 1.) .git/configФайл указывает, что репозитории пустые. 2.) Файлы, обычно хранящиеся в .git, хранятся в корне (который вы назвали .git)
mozey
4
Это именно те изменения, к которым будут относиться клонирование .gitи настройка , поэтому я все еще чувствую себя хорошо в этом методе. core.barefalse
Кен Уильямс
10

Это сработало для меня:

cd existing_folder
git init
git remote add origin path_to_your_repo.git
git add .
git commit
git push -u origin master
Mike6679
источник
6

У меня была похожая проблема с новым веб-каталогом Apache (учетная запись, созданная с помощью WHM), которую я планировал использовать в качестве промежуточного веб-сервера. Сначала мне нужно было клонировать мой новый проект с базой кода и периодически вносить изменения, извлекая данные из репозитория.

Проблема заключалась в том, что учетная запись уже содержала файлы веб-сервера, такие как:

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

... что я не хотел ни удалять, ни фиксировать в своем хранилище. Мне нужно было, чтобы они оставались там без посторонних и неотслеживаемых.

Что я сделал:

Я пошел в свою веб-папку (существующая_фолдер):

cd /home/existing_folder

а потом:

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

Он отображал (как и ожидалось) список многих не подготовленных файлов - тех, которые изначально существовали в моей учетной записи cPanel.

Затем, благодаря этой статье , я просто добавил список этих файлов в:

**.git/info/exclude**

Этот файл, почти как .gitignoreфайл, позволяет вам игнорировать файлы от постановки. После этого мне нечего было коммитить в каталог .git / - он работает как личный.gitignore который никто не может увидеть.

Теперь проверяем git statusвозвраты:

On branch master
nothing to commit, working tree clean

Теперь я могу развернуть изменения на этом веб-сервере, просто извлекая данные из моего репозитория git. Надеюсь, что это поможет некоторым веб-разработчикам легко создать промежуточный сервер.

Владо
источник
5

Вот что я делаю:

git clone repo /tmp/folder
cp -rf /tmp/folder/.git /dest/folder/
cd /dest/folder
git checkout -f master
Филип Киркбрайд
источник
4

Может быть, я неправильно понял ваш вопрос, но не проще ли скопировать / переместить файлы из A в git repo B и добавить нужные с помощью git add ?

ОБНОВЛЕНИЕ: Из Git Doc:

Клонирование в существующий каталог допускается только в том случае, если каталог пуст.

ИСТОЧНИК: http://git-scm.com/docs/git-clone

Роберто Алои
источник
2
Нет, владелец и файлы могут быть произвольными. Это для ситуации с несколькими разработчиками. У всех нас есть существующие каталоги, и только один в настоящее время имеет git checkout. У всех нас в основном одно и то же подмножество файлов, поэтому мы хотим, чтобы другие разработчики могли клонировать, сохраняя свои файлы. И это должно быть максимально элегантно и удобно.
Дейл Форестер
Честно говоря, я не вижу смысла развиваться в таком состоянии. Разве вы не можете использовать ветви и операции слияния? Или иметь суб-репозитории с внешними зависимостями? Почему вы хотите положиться на одну «git checkout»?
Роберто Алои
5
«Одиночный git checkout» - это не главное испытание. Просто так оно и есть, и нам нужен способ двигаться вперед. Я обновил исходный вопрос решением, которое, кажется, работает. Я ценю обратную связь, хотя.
Дейл Форестер
3
Есть много законных случаев для этого - у меня есть сложное дерево папок, которое необходимо настроить ДО того, как можно будет установить источник моего проекта, и это дерево папок содержит лицензионные работы, которые не могут быть сохранены, например, на GitHub.
BrainSlugs83
3

Я искал что-то похожее, и вот что я придумал:

У меня ситуация, когда у меня есть активное веб-дерево, и я пытался создать для него удаленный репозиторий без перемещения каких-либо файлов в текущем веб-дереве. Вот что я сделал:

  1. Перейти в веб-дерево и запустить git init
  2. Перейдите в предполагаемое местоположение хранилища и запустите: git clone --bare /path/to/web/repo
  3. Отредактируйте файл конфигурации в моем удаленном репо и удалите [remote "origin"]раздел.
  4. Добавьте [remote "origin"]раздел в .git / config в веб-дереве, указывающий на новое удаленное хранилище.
Lendrick
источник
Мне очень нравится этот рецепт.
Дланд
git clone --bareЗдесь излишни и обходные. Почему бы просто не git remote add origin <URL>в первую очередь?
Араксия
3

это работа для меня, но вы должны объединить файлы удаленного репозитория с локальными файлами:

git init
git remote add origin url-to-git
git branch --set-upstream-to=origin/master master
git fetch
git status
РОДНИ ЖАН
источник
1

Мне понравился ответ Дейла , и я также добавил

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

Малая глубина избежала множества дополнительных ранних изменений. Новая ветка дала нам хорошую визуальную историю, что был добавлен новый код с этого сервера. На мой взгляд, это идеальное использование веток. Спасибо большое за понимание всех людей, которые разместили здесь.

Дмитрий R117
источник
0

У меня такие же проблемы при попытке клонировать в c / code

Но эта папка содержит целую кучу проектов.

Я создал новую папку в c / code / newproject и сопоставил свой клон с этой папкой.

git для рабочего стола затем спросил моего пользователя, а затем клонируется нормально.

Том
источник