¿Cuál es la mejor práctica para "git clone" en una carpeta existente?


480

Tengo una copia de trabajo del proyecto, sin ningún metadato de control de origen. Ahora, me gustaría hacer el equivalente de git-clone en esta carpeta y mantener mis cambios locales.

git-clone no me permite clonar en una carpeta existente. ¿Cuál es la mejor práctica aquí?


44
Mejor discusión está aquí .
cdunn2001

1
@MEM Me gusta más esta respuesta, pero tampoco funciona ... stackoverflow.com/a/5377989/11236
ripper234

2
@ ripper234 - Sí. Estaba en la misma situación y solo hice esos pasos, y no tuve problemas. Todo limpio y agradable. Supongo que es una cuestión de preferencia, siendo el resultado final, que ambos funcionan, como usted dice. Salud.
MEM

1
Esto es tan loco que no hay una manera limpia de lograrlo, tan útil cuando desea clonar un proyecto en una carpeta compartida montada.
Thomas Decaux

Respuestas:


559

Esto se puede hacer clonando a un nuevo directorio, luego moviendo el .git directorio a su directorio existente.

Si su directorio existente se llama "código".

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

Esto también se puede hacer sin realizar un pago durante el comando clonar; Más información se puede encontrar aquí .


25
Tenga en cuenta que esta es exactamente la sugerencia de @ChrisJohnsen que dejó en los comentarios. Lo encontré útil y quería convertirlo en una respuesta real. Chris, si terminas poniendo una respuesta, felizmente eliminaré esta.
amicitas

2
¡Gracias! Aunque a este le falta un paso como "git checkout -". ya que piensa que todos los archivos se eliminan, ¿verdad?
mrooney

2
No, siempre y cuando lo use git clonecomo primer comando, no se necesita más comando de pago. Si en su lugar usa algo como git clone --no-checkouten ese primer paso, luego de mover el directorio .git será necesario usarlo git reset HEADpara decirle a git que los archivos no se han eliminado.
amicitas

3
Agregaría esto como tercer paso: mv temp / .gitignore code / .gitignore
Daniel Aranda

1
@KalpeshSoni, sí, git sabrá acerca de los archivos modificados y será posible ver los cambios utilizando los comandos normales de git como git status.
amicitas

284

No clones, busca en su lugar. En el repositorio:

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

Luego puede restablecer el árbol para obtener la confirmación que desea:

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

y eres como clonado

La pregunta interesante aquí (y la que no tiene respuesta): cómo averiguar en qué compromiso se basó su árbol desnudo, por lo tanto, en qué posición restablecer.


77
No soy fanático de esto, según la configuración de github "Sugerencia: el asistente de credenciales solo funciona cuando clonas una URL de repositorio HTTPS". Estaba usando credencial de ayuda y esto me envió por una madriguera de conejo larga y bastante infructuosa.
Andrew

55
'git checkout --track origin / master' también funciona bien en lugar de 'git checkout -b master --track origin / master'. El reinicio no es necesario.
felipecrp

1
Recibí el error "Error de Git: los siguientes archivos de árbol de trabajo sin seguimiento se sobrescribirán al finalizar la compra", así que
agregué

1
Definitivamente no es aconsejable en todas las situaciones, pero esto es exactamente lo que necesitaba.
Chaim Eliyah

1
@AndreasKrey Su respuesta original (que vi en el historial de edición para ver) hace exactamente lo que necesita la pregunta (y yo). La respuesta modificada barfs en el pago sin usar -f, que descarta los cambios locales y es exactamente lo que no quiero. Si yo fuera tú, consideraría volver a tu respuesta original.
Ajean

77

Lo siguiente que hice, para pagar la rama maestra en un directorio existente:

git init
git remote add origin [my-repo]
git fetch
git checkout origin/master -ft

2
Esta es una gran respuesta y evita cualquier desorganización del sistema de archivos.
user151841

1
Esta debería ser la respuesta aceptada, ya que no es un truco.
php_nub_qq

55
En realidad, esto hace exactamente lo que el OP (y yo) no queremos, que es sobrescribir los cambios locales.
Ajean

Mi voto positivo indica que esto me ayudó, no es la mejor respuesta a la pregunta del OP.
TecBrat

2
¿Alguien puede explicar por qué -tse usa la bandera aquí?
jfowkes

38

Me gustaría git clonea un nuevo directorio y copiar el contenido del directorio existente al nuevo clon.


44
si hace eso, asegúrese de revisar el diff antes de comprometerse con mucho cuidado; este es un caso clásico absoluto en el que puede revertir accidentalmente los cambios que se hicieron en el repositorio fuente desde que obtuvo su copia de trabajo, porque no hay suficiente información en la copia de trabajo para averiguar qué cambios realizó frente a cómo eran antes de comenzar a realizar cambios, para fusionarse con otros cambios realizados en el repositorio. He visto que esto sucede una y otra vez en esta situación, hasta el punto de que "me desanimé" a mí mismo ya las personas con las que trabajé para que nunca lo hicieran.
Ben Clifford

72
git clone wherever tmp && git mv tmp/.git . && rm -rf tmpEn otras palabras, mover el .gitdirectorio de un clon temporal parece más simple que limpiar el árbol de trabajo del clon y copiar los archivos existentes allí.
Chris Johnsen

1
@ChrisJohnsen: deberías haberlo convertido en una respuesta, esa es definitivamente la mejor manera de hacerlo en mi humilde opinión
Stefano

2
@ChrisJohnsen git mv tmp/.git .regresa fatal: cannot move directory over file, source=tmp/.git, destination=.gitpor mí. Alguien sabe cuál es el problema?
Dennis

66
@ Dennis, es un error tipográfico: ese comando debe ser simple mv, no git mv; aunque esto no explica por qué ya tiene un .gitarchivo allí (que contiene gitdir: some/path/to/a/git-dirun "archivo git"; si no estuviera allí, entonces lo habría visto fatal: Not a git repository (or any of the parent directories): .git).
Chris Johnsen

34

El uso de un directorio temporal está bien, pero esto funcionará si desea evitar ese paso. Desde la raíz de su directorio de trabajo:

$ rm -fr .git
$ git init
$ git remote add origin your-git-url
$ git fetch
$ git reset --mixed origin/master

20
git reset --hard origin/mastereliminará todos los archivos locales.
Mouad Debbar el

1
para agregar a lo que ya se señaló anteriormente, la diferencia entre hard y mixedes que mixto mantendrá los cambios locales (por lo tanto, si luego intentas tirar, te mostrará, por ejemplo, no se puede tirar con rebase: tienes cambios no organizados. Compruébalo o guárdalos ) , aunque difícil descartará esos cambios locales
aexl

Has escrito mal a distancia.
Glenn Dayton

10
git clone your_repo tmp && mv tmp/.git . && rm -rf tmp && git reset --mixed

77
El uso git reset --hardeliminará los cambios en el archivo local, específicamente NO lo que solicitó este OP. --mixeddebería usarse en su lugar.
Caleb

4

Para clonar un repositorio git en un directorio existente vacío, haga lo siguiente:

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

Observe el .al final de su git clonecomando. Eso descargará el repositorio en el directorio de trabajo actual.


44
fatal: destination path '.' already exists and is not an empty directory.
Roland Kofler

El directorio debe estar vacío.
okTalk

44
El OP pregunta cómo clonar en un proyecto existente, afirmando que git clone se queja. Mala respuesta.
mix3d

Esto funciona solo cuando crea un nuevo directorio, ejecute los comandos anteriores sin usar "git init"
Bilal Ahmed

3

Muchas respuestas ya para hacerlo de la manera en que lo solicitó el OP. Pero vale la pena señalar que hacerlo al revés es mucho más simple:

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

Ahora tiene el estado objetivo deseado: clon fresco + cambios locales.


2

Hay dos enfoques para esto. Siempre que sea posible, comenzaría con una carpeta limpia para su nuevo directorio de trabajo de git y luego copiaría su versión de las cosas más adelante. Esto podría parecerse a *:

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

En este punto, debe tener una copia de trabajo bastante limpia con su carpeta de trabajo anterior como el directorio de trabajo actual, por lo que cualquier cambio que incluya la eliminación de archivos aparecerá en el radar si ejecuta git status .

Por otro lado, si realmente debe hacerlo al revés, puede obtener el mismo resultado con algo como esto:

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

De cualquier manera, lo primero que haría es ejecutar algo como git stash obtener una copia de todos sus cambios locales, luego puede volver a aplicarlos y determinar a través de cuáles desea comprometerse.

* Ambos ejemplos asumen que comienzas en el shell en el directorio principal de tu proyecto.


2

Este es el mejor de todos los métodos que encontré

Clone solo la carpeta .git del repositorio (excluyendo archivos ya que están en existing-dir) en un directorio temporal vacío

  1. git clone --no-checkout repo-path-to-clone existing-dir/existing-dir.tmp // podría querer --no-hardlinks para clonar repositorio local

Mueva la carpeta .git al directorio con los archivos. Esto hace existing-dirun repositorio git.

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

Eliminar el directorio temporal

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

  2. cd existing-dir

Git piensa que todos los archivos se eliminan, esto revierte el estado del repositorio a HEAD.

ADVERTENCIA: cualquier cambio local en los archivos se perderá.

  1. git reset --mixed HEAD

1
Un restablecimiento completo parece no deseado en el 99% de los casos en los que necesitaría hacer esto.
Stefan Fabian

0

Si está utilizando al menos git 1.7.7 (que enseñó clonela --configopción), para convertir el directorio actual en una copia de trabajo:

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

Esto funciona por:

  • Clonando el repositorio en un nuevo .git carpeta
  • --mirror convierte el nuevo clon en una carpeta puramente de metadatos como .git necesario
  • --config core.bare=falsecontradice lo implícito bare=truede la --mirroropción, permitiendo así que el repositorio tenga un directorio de trabajo asociado y actúe como un clon normal

Obviamente, esto no funcionará si .gitya existe un directorio de metadatos en el directorio que desea convertir en una copia de trabajo.


1
Tenga en cuenta que esta técnica dará como resultado la [core]sección de la configuración local que incluye ambos bare = true y bare = false . Más problemático es que tendrá valores incorrectos para el origincontrol remoto, con la [remote "origin"]sección incluida mirror = truey una especificación de búsqueda que no funcionará correctamente con una copia de trabajo. Después de solucionar estos problemas, clonar normalmente y mover las nuevas copias de trabajo .githabrá sido más eficiente.
Araxia

0

Por lo general, clonaré primero el repositorio inicial y luego moveré todo el contenido de la carpeta existente al repositorio inicial. Funciona todo el tiempo.

La ventaja de este método es que no se perderá nada del repositorio inicial, incluido README o .gitignore.

También puede usar el siguiente comando para finalizar los pasos:

$ git clone https://github.com/your_repo.git && mv existing_folder/* your_repo

0

Puede hacerlo escribiendo las siguientes líneas de comando de forma recursiva:

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

0

Solo usa el. al final del git clonecomando (estar en ese directorio), así:

cd your_dir_to_clone_in/
git clone git@github.com/somerepo/ .

No funciona: fatal: ruta de destino '.' ya existe y no es un directorio vacío.
Tristan CHARBONNIER
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.