¿Cómo clono en un directorio no vacío?

573

Tengo el directorio A con archivos que coinciden con el directorio B. El directorio A puede tener otros archivos necesarios. El directorio B es un repositorio git.

Quiero clonar el directorio B en el directorio A pero git-clone no me lo permite ya que el directorio no está vacío.

Esperaba que solo clonara .git y, dado que todos los archivos coinciden, ¿podría ir desde allí?

No puedo clonar en un directorio vacío porque tengo archivos en el directorio A que no están en el directorio B y quiero conservarlos.

Copiar .git no es una opción, ya que quiero que los refs empujen / tiren y no quiero configurarlos manualmente.

¿Hay alguna forma de hacer esto?

Actualización: creo que esto funciona, ¿alguien puede ver algún problema? ->

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
fuente
55
tal vez podrías cambiar la respuesta aceptada?
Bastiaan Quast

Respuestas:

724

Esto funcionó para mí:

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

NOTA: -t establecerá la rama ascendente para usted, si eso es lo que desea, y generalmente lo es.

cmcginty
fuente
70
Esto no funciona en un directorio no vacío cuando los archivos entrantes ya existen (como se describe en la pregunta original). Pero si git reset origin/masterdespués de git fetcheso, funcionará (también preservando cualquier cambio local).
Araxia
8
fatal: no se pueden actualizar las rutas y cambiar a la rama 'maestro' al mismo tiempo.
Arnold Roa
77
Esta respuesta no me funciona. Cuando hago git checkout ...git se queja de que todos mis archivos se sobrescribirán y debería moverlos primero. Cuando hago `git reset origin / master /` primero, el comando de pago se queja de que ya existe una rama llamada master.
Saskia
44
git checkout masterFue un paso final suficiente para mí.
yoyo
16
Todos los pasos funcionó a la perfección pero el último me tienen: fatal: A branch named 'master' already exists. Creo que realmente no lo necesitaba.
Shadi
164

En los siguientes comandos de shell existing-dirhay un directorio cuyo contenido coincide con los archivos rastreados en el repo-to-clonerepositorio de 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
fuente
55
Tenía que hacerlo git reset --hard HEADo no se daría por vencido en los archivos "eliminados".
Dimitar
18
git reset HEADfuncionó bien para mí git reset --hard HEADdestruye cualquier cambio en sus archivos, por lo que si no son exactamente los mismos que los archivos en el repositorio, no debe hacer eso.
Tgr
1
git reset HEADNo parece tener ningún efecto para mí. git reset --hard HEADsí, pero eso pierde cualquier cambio que haya realizado en los archivos. ¿Hay una mejor solución?
Jacob Dorman
1
La respuesta de @ Casey - git init / remote add / fetch / checkout - es más limpia y simple y no requiere ninguna carpeta temporal.
yoyo
1
La respuesta de @ Casey no funcionó para mí cuando ya había archivos en carpetas que debían permanecer pero que no estaban en el repositorio de git. Esto es útil para actualizar la configuración después de ejecutar scripts de instalación donde se crean archivos y directorios pero necesita actualizar / agregar archivos sobre los elementos instalados.
soulston
104

Una ligera modificación a una de las respuestas que me funcionó:

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

para comenzar a trabajar en la rama maestra de inmediato.

mohsaied
fuente
1
tuvo que restablecer HEAD --duro para limpiar el directorio existente sucio, sin eliminar los archivos irrelevantes especificados en gitignore
Ray Foss
1
Este es el que realmente funcionó para mí, a diferencia de la respuesta de @ cmcginty.
ciertamente
44
Esto no es del todo equivalente a un clon git: lo que falta es la información ascendente para la rama maestra. Esto se puede solucionar agregando git branch --set-upstream-to=origin/master master.
Slaven Rezic
Esta versión funcionó para mí, solo tuve que hacer un reinicio de git --hard HEAD
Frédéric Klee
29

Advertencia: esto podría sobrescribir los archivos.

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

Modificado de la respuesta de @ cmcginty - sin el -f no funcionó para mí

JohnFF
fuente
¿Seguramente necesita verificar todos los archivos después de esto con git checkout .?
Chris Stryczynski el
25

Esto es lo que terminé haciendo cuando tuve el mismo problema (al menos creo que es el mismo problema). Entré en el directorio A y corrí git init.

Como no quería que los archivos en el directorio A fueran seguidos por git, edité .gitignore y agregué los archivos existentes. Después de esto corrí git remote add origin '<url>' && git pull origin masteret voíla, B es "clonado" en A sin un solo contratiempo.

BjornSnoen
fuente
2
Esta técnica no funciona en un directorio no vacío cuando los archivos entrantes ya existen (como se describe en la pregunta original).
Araxia
11

Lo he usado hace unos momentos, requiere los comandos menos potencialmente destructivos:

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

¡Y voilá!

KuttKatrea
fuente
10

Otra receta simple parece funcionar bien para mí:

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

Mi principal caso de uso para revisar un directorio con archivos existentes es controlar mis archivos de puntos Unix con Git. En una cuenta nueva, el directorio de inicio ya tendrá algunos archivos, posiblemente incluso los que quiero obtener de Git.

Ken Williams
fuente
1
Los repositorios desnudos se configuran de manera un poco diferente y, aunque esto funciona, no lo recomendaría. :)
ThorSummoner
1
¿Puedes ser mas específico? ¿Que es diferente?
Ken Williams
1
Solo dos diferencias: 1.) El .git/configarchivo indica que los repos están vacíos. 2.) Los archivos normalmente almacenados .gitse almacenan en la raíz (que usted llamó .git)
mozey
44
Esos son exactamente los cambios que la clonación .gity configuracióncore.bare a falsese hará cargo de, por lo que todavía me siento bien acerca de este método.
Ken Williams
10

Esto funcionó para mí:

cd existing_folder
git init
git remote add origin path_to_your_repo.git
git add .
git commit
git push -u origin master
Mike6679
fuente
6

Tuve un problema similar con un nuevo directorio web de Apache (cuenta creada con WHM) que planeaba usar como servidor web provisional. Necesitaba clonar inicialmente mi nuevo proyecto con la base de código allí e implementar periódicamente cambios al extraer del repositorio.

El problema era que la cuenta ya contenía archivos del servidor web como:

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

... que no quería eliminar ni confirmar en mi repositorio. Necesitaba que se quedaran allí sin escena ni seguimiento.

Lo que hice:

Fui a mi carpeta web (carpeta_existente):

cd /home/existing_folder

y entonces:

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

Mostraba (como se esperaba) una lista de muchos archivos no organizados, aquellos que ya existían inicialmente desde mi cuenta web de cPanel.

Luego, gracias a este artículo , acabo de agregar la lista de esos archivos a:

**.git/info/exclude**

Este archivo, casi como el .gitignorearchivo, le permite ignorar los archivos que se organizarán. Después de esto, no tuve nada que comprometer en el directorio .git /, funciona como un personal.gitignore que nadie más puede ver.

Ahora comprobando git statusdevoluciones:

On branch master
nothing to commit, working tree clean

Ahora puedo implementar cambios en este servidor web simplemente extrayendo de mi repositorio git. Espero que esto ayude a algunos desarrolladores web a crear fácilmente un servidor provisional.

Vlado
fuente
5

Esto es lo que estoy haciendo:

git clone repo /tmp/folder
cp -rf /tmp/folder/.git /dest/folder/
cd /dest/folder
git checkout -f master
Philip Kirkbride
fuente
4

Tal vez entendí mal su pregunta, pero ¿no sería más simple si copia / mueve los archivos de A al repositorio de git B y agrega los necesarios con git add ?

ACTUALIZACIÓN: desde el documento de git:

La clonación en un directorio existente solo se permite si el directorio está vacío.

FUENTE: http://git-scm.com/docs/git-clone

Roberto Aloi
fuente
2
No, el propietario y los archivos pueden ser arbitrarios. Esto es para una situación con múltiples desarrolladores. Todos tenemos directorios existentes y solo uno actualmente tiene un pago git. Todos tenemos en gran medida el mismo subconjunto de archivos, por lo que queremos que los otros desarrolladores puedan clonar mientras retienen sus archivos. Y debe ser lo más elegante y conveniente posible.
Dale Forester
Honestamente, no veo el punto de desarrollarme en tal condición. ¿No puedes usar sucursales y operaciones de fusión? ¿O tener sub-repositorios con dependencias externas? ¿Por qué querrías confiar en un solo "git checkout"?
Roberto Aloi
55
Una "compra de un solo git" no es el punto de toda la prueba. Es solo que así es y necesitamos una forma de avanzar. Actualicé la pregunta original con una solución que parece estar funcionando. Sin embargo, aprecio los comentarios.
Dale Forester
3
Hay muchos casos legítimos para esto: tengo un árbol de carpetas complejo que se debe configurar ANTES de que se pueda configurar la fuente de mi proyecto, y ese árbol de carpetas contiene trabajos con licencia que no se pueden almacenar en GitHub, por ejemplo.
BrainSlugs83
3

Estaba buscando algo similar, y esto es lo que se me ocurrió:

Mi situación es una en la que tengo un árbol web activo e intentaba crear un repositorio remoto para él sin mover ninguno de los archivos en el árbol web actual. Esto es lo que hice:

  1. Ve al árbol web y corre git init
  2. Vaya a la ubicación prevista del repositorio y ejecute: git clone --bare /path/to/web/repo
  3. Edite el archivo de configuración en mi repositorio remoto y elimine la [remote "origin"]sección.
  4. Agregue una [remote "origin"]sección a .git / config en el árbol web que apunte al nuevo repositorio remoto.
Lendrick
fuente
Me gusta mucho esta receta.
Dland
El git clone --bareaquí es superfluo y tortuoso. ¿Por qué no solo git remote add origin <URL>en primer lugar?
Araxia
3

esto es un trabajo para mí, pero debe fusionar los archivos de repositorio remotos con los archivos locales:

git init
git remote add origin url-to-git
git branch --set-upstream-to=origin/master master
git fetch
git status
RODNEY ZHANG
fuente
1

Me gustó la respuesta de Dale , y también agregué

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

La poca profundidad evitó muchos compromisos de desarrollo tempranos adicionales. La nueva sucursal nos dio una buena historia visual de que había un nuevo código de este servidor que se colocó. Ese es el uso perfecto de las sucursales en mi opinión. Mi agradecimiento a la gran comprensión de todas las personas que publicaron aquí.

Dmitri R117
fuente
0

Tengo los mismos problemas al intentar clonar a c / code

Pero esta carpeta contiene una gran cantidad de proyectos.

Creé una nueva carpeta en c / code / newproject y asigné mi clon a esta carpeta.

git para escritorio luego le pregunté a mi usuario y luego cloné bien.

Tom
fuente