¿Cómo convertir un repositorio Git normal a uno desnudo?

603

¿Cómo puedo convertir un repositorio Git 'normal' en uno desnudo?

La principal diferencia parece ser:

  • en el repositorio normal de Git, tiene una .gitcarpeta dentro del repositorio que contiene todos los datos relevantes y todos los demás archivos que componen su copia de trabajo

  • en un repositorio Git desnudo, no hay una copia de trabajo y la carpeta (llamémosla repo.git) contiene los datos reales del repositorio

Boldewyn
fuente
16
Presumiblemente este es un método más corto:mv repo/.git repo.git; rm -rf repo
jameshfisher
Si verdad. Cuando escribí la pregunta, este fue solo el fragmento de mi historia, que ejecuté el otro minuto.
Boldewyn
54
@eegg ¡Use en &&lugar de ;en caso de que mvfalle!

Respuestas:

610

En resumen: reemplace el contenido de repocon el contenido de repo/.git, luego dígale al repositorio que ahora es un repositorio desnudo.

Para hacer esto, ejecute los siguientes comandos:

cd repo
mv .git ../repo.git # renaming just for clarity
cd ..
rm -fr repo
cd repo.git
git config --bool core.bare true

Tenga en cuenta que esto es diferente de hacer git clone --bareuna nueva ubicación (ver más abajo).

Jörg W Mittag
fuente
99
Gracias por la pista a core.bare. Ahora, después de buscar en Google esta opción, puedo confirmarla: kernel.org/pub/software/scm/git-core/docs/git-config.html
Boldewyn
14
¡Gracias! Esto me parece más limpio: mv repo / .git repo.git && rm -rf repo && cd repo.git && git config --bool core.bare true
JasonWoof
56
Esto es mucho más complicado y frágil que la respuesta a continuación ( git clone --bare /path/to/repo).
djd
77
Ese rmcomando puede necesitar en * \.[!.]*lugar de *eliminar archivos de puntos y directorios de puntos.
minopret
66
@Ciantic: Nuevamente, como ya expliqué en mi comentario anterior, mi respuesta se dio hace 3 años, pero hace 5 meses alguien editó la pregunta en algo completamente diferente. Ninguna de las respuestas en esta página hará ningún sentido. Esa secuencia de comandos se copió directamente de la pregunta, acabo de agregar las dos últimas líneas.
Jörg W Mittag
244

Parece que su método funcionaría; La estructura de archivos de un repositorio simple es justo lo que está dentro del directorio .git. Pero no sé si alguno de los archivos se cambia realmente, por lo que si eso falla, simplemente puede hacer

git clone --bare /path/to/repo

Probablemente necesitará hacerlo en un directorio diferente para evitar un conflicto de nombres, y luego puede moverlo nuevamente a donde desee. Y es posible que deba cambiar el archivo de configuración para que apunte a donde esté su repositorio de origen.

jonescb
fuente
50
Mal, este método no es el equivalente. Hacer un clon no conserva las opciones de configuración, que pueden ser críticas para un funcionamiento adecuado, como si usa git-p4. Además, un clon destruye los controles remotos, nuevamente con algo como git-p4 pierde la rama p4 / master cuando clona, ​​por lo que es preferible el enfoque anterior.
nosatalian
26
Pero puede transferir fácilmente las opciones de configuración copiando las partes respectivas del archivo de configuración. Todavía consideraría que este método es más limpio que copiar y renombrar archivos manualmente.
Philipp
66
Esto es perfecto después de una migración de subversión ya que git-svn carece de soporte para --bare.
Keyo
11
Para evitar el conflicto de nombres ---git clone --bare /path/to/repo.git /path/to/newbarerepo.git
raksja
Esto funciona siempre y cuando se ejecute git update-server-infoen el repositorio desnudo después de la creación.
ACK_stoverflow
116

Creo que el siguiente enlace sería útil

GitFaq: ¿Cómo hago desnudo el repositorio no descubierto existente?

$ mv repo/.git repo.git
$ git --git-dir=repo.git config core.bare true
$ rm -rf repo
xhh
fuente
2
Sí, eso es lo que busqué, ¡gracias! Sin embargo, su segunda propuesta ( git clone) tiene los inconvenientes que nosatalian mencionó anteriormente.
Boldewyn
1
La documentación que sugirió continúa: "Un método más seguro es dejar que Git maneje todas las configuraciones internas por usted haciendo algo como esto ... git clone --bare -l <path_to_repos> <new_dir>"
dafunker
74

A menos que específicamente desee o necesite girar bits en el sistema de archivos, realmente es muy sencillo crear una versión desnuda de un repositorio no desnudo (mencionado en varias otras publicaciones aquí). Es parte de la funcionalidad principal de git:

git clone --bare existing_repo_path bare_repo_path

Chip Kaye
fuente
66
Es sorprendente que la mejor respuesta de lejos tenga 0 votos después de> 4 meses. ¡La 'respuesta aceptada' no muy buena pero peligrosa tiene 200!
Stabledog
36
No es sorprendente en absoluto: esta respuesta no hace lo que se hizo la pregunta original. No convierte un repositorio, clona uno, perdiendo información en el proceso (por ejemplo, ramas remotas).
GreenAsJade
15

Por favor también considere usar

git clone --mirror path_to_source_repository

De la documentación :

Configure un espejo del repositorio de origen. Esto implica --desnudo. En comparación con --bare, --mirror, no solo asigna las ramas locales de la fuente a las ramas locales del objetivo, sino que asigna todas las referencias (incluidas las ramas de seguimiento remoto, notas, etc.) y establece una configuración de referencia de referencia para que todas estas referencias son sobrescritos por una actualización remota de git en el repositorio de destino.

Jacek Krawczyk
fuente
Parece que esta es la forma más concisa, completa y segura de hacer lo que quiere el OP (vs. solo clone). ¿Me estoy perdiendo de algo? ¿Fue --mirroruna adición relativamente reciente?
Craig Silver
@CraigSilver: No, como veo en el historial de documentación de tal forma, --mirrorestá disponible desde la versión 1.7, por lo que ya es bastante largo. Puedes ver aquí
Jacek Krawczyk
7

Solo quería pasar a un repositorio en una ruta de red, pero git no me dejaba hacer eso a menos que ese repositorio estuviera marcado como vacío. Todo lo que necesitaba era cambiar su configuración:

git config --bool core.bare true

No es necesario jugar con los archivos a menos que desee mantenerlo limpio.

Slion
fuente
3
Esto es peligroso cuando también desea trabajar en el árbol de trabajo del repositorio remoto. Lo más probable es que tarde o temprano revierta un cambio simplemente porque su árbol de trabajo remoto e índice no estaban sincronizados con el repositorio. No recomiendo esta solución, si no sabes exactamente lo que estás haciendo.
Boldewyn
Es cierto que no debe trabajar en el árbol del repositorio remoto remoto.
Slion
6

He leído las respuestas y he hecho esto:

cd repos
mv .git repos.git
cd repos.git
git config --bool core.bare true # from another answer
cd ../
mv repos.git ../
cd ../
rm -rf repos/ # or delete using a file manager if you like

esto dejará el contenido repos/.gitcomo desnudorepos.git

Dan D.
fuente
4

Esto es lo que creo que es más seguro y simple. No hay nada aquí no mencionado anteriormente. Solo quiero ver una respuesta que muestre un procedimiento seguro paso a paso. Comienza una carpeta desde el repositorio (repositorio) que desea dejar al descubierto. Adopté la convención implícita arriba de que las carpetas de repositorio desnudas tienen una extensión .git.

(1) Backup, just in case.
    (a) > mkdir backup
    (b) > cd backup
    (c) > git clone ../repo
(2) Make it bare, then move it
    (a) > cd ../repo
    (b) > git config --bool core.bare true
    (c) > mv .git ../repo.git
(3) Confirm the bare repository works (optional, since we have a backup)
    (a) > cd ..
    (b) > mkdir test
    (c) > cd test
    (d) > git clone ../repo.git
(4) Clean up
    (a) > rm -Rf repo
    (b) (optional) > rm -Rf backup/repo
    (c) (optional) > rm -Rf test/repo
sdesciencelover
fuente
1
esto no es mucho más seguro ya que hizo su copia de seguridad usando git clone. La copia de seguridad mediante clonación hará que pierda algunas configuraciones, que en ciertos casos pueden ser críticas para el repositorio.
Lie Ryan
Célebre. Las únicas configuraciones que me han importado son globales para todos mis repositorios locales.
sdesciencelover
4

Simplemente lee

Pro Git Book: 4.2 Git en el servidor - Obtener Git en un servidor

que se reducen a

$ git clone --bare my_project my_project.git
Cloning into bare repository 'my_project.git'...
done.

Luego ponga my_project.git en el servidor

Lo cual es principalmente, qué respuesta # 42 trató de señalar. Shurely uno podría reinventar la rueda ;-)

apos
fuente
No puedo ver, lo que agrega esta respuesta, que no se ha discutido de manera arbitraria en ninguna de las otras respuestas (incluidas las votadas negativamente). ¿Podrías aclararlo por favor? (Por cierto: el Libro Pro Git dice "Esto es más o menos equivalente a algo así como ..." , y esa equivalencia aproximada exacta también ya se discute aquí.)
Boldewyn
3

Aquí hay una pequeña función BASH que puede agregar a su .bashrc o .profile en un sistema basado en UNIX. Una vez agregado y el shell se reinicia o el archivo se vuelve a cargar mediante una llamada a source ~/.profileo source ~/.bashrc.

function gitToBare() {
  if [ -d ".git" ]; then
    DIR="`pwd`"
    mv .git ..
    rm -fr *
    mv ../.git .
    mv .git/* .
    rmdir .git

    git config --bool core.bare true
    cd ..
    mv "${DIR}" "${DIR}.git"

    printf "[\x1b[32mSUCCESS\x1b[0m] Git repository converted to "
    printf "bare and renamed to\n  ${DIR}.git\n"
    cd "${DIR}.git"
  else
    printf "[\x1b[31mFAILURE\x1b[0m] Cannot find a .git directory\n"
  fi
}

Una vez llamado dentro de un directorio que contiene un directorio .git, realizará los cambios apropiados para convertir el repositorio. Si no hay un directorio .git presente cuando se llama, aparecerá un mensaje de FALLA y no se producirán cambios en el sistema de archivos.

Nyteshade
fuente
1

Los métodos que dicen eliminar archivos y perder el tiempo moviendo el directorio .git no están limpios y no usan el método "git" para hacer algo que debería ser simple. Este es el método más limpio que he encontrado para convertir un repositorio normal en un repositorio simple.

Primer clon / ruta / a / normal / repo en un repositorio desnudo llamado repo.git

git clone --bare /path/to/normal/repo

Luego, elimine el origen que apunta a / ruta / a / normal / repo

cd repo.git
git remote rm origin

Finalmente puedes eliminar tu repositorio original. Puede cambiar el nombre de repo.git a repo en ese punto, pero la convención estándar para indicar un repositorio git es algo.git, por lo que personalmente lo dejaría de esa manera.

Una vez que haya hecho todo eso, puede clonar su nuevo repositorio desnudo (que en efecto crea un repositorio normal, y también es cómo lo convertiría de desnudo a normal)

Por supuesto, si tiene otras fuentes ascendentes, tendrá que anotarlas y actualizar su repositorio para incluirlo. Pero de nuevo, todo se puede hacer con el comando git. Recuerda que las páginas del manual son tu amigo.

krux
fuente
1
¿Te has molestado en leer las otras respuestas? ¿Especialmente el comentario de @ jonescb y @ nosatalian? El método "git" es el siguiente: "Haz todo lo posible con archivos de texto sin formato". Debería comenzar a investigar las partes internas de una .gitcarpeta. Es muy educativo aprender cómo encajan las partes.
Boldewyn
1

En caso de que tenga un repositorio con pocas sucursales / referencias / encabezados de pago local / pocas sucursales remotas remotas / origen / * Y si desea convertir esto en un repositorio BARE con todas las sucursales en / refs / heads / *

Puede hacer lo siguiente para guardar el historial.

  1. crear un repositorio desnudo
  2. cd en el repositorio local que tiene sucursales de pago local y sucursales remotas
  3. git push / path / to / bare / repo + refs / remotes / origin / : refs / heads /
Senthil A Kumar
fuente
0

Usé el siguiente script para leer un archivo de texto que tiene una lista de todos mis repositorios SVN y convertirlos a GIT, y luego usar git clone --bare para convertir a un repositorio git desnudo

#!/bin/bash
file="list.txt"
while IFS= read -r repo_name
do
 printf '%s\n' "$repo_name"
 sudo git svn clone --shared --preserve-empty-dirs --authors-file=users.txt file:///programs/svn/$repo_name 
 sudo git clone --bare /programs/git/$repo_name $repo_name.git
 sudo chown -R www-data:www-data $repo_name.git
 sudo rm -rf $repo_name
done <"$file"

list.txt tiene el formato

repo1_name
repo2_name

y users.txt tiene el formato

(no author) = Prince Rogers <[email protected]>

www-data es el usuario del servidor web Apache, se necesita permiso para impulsar los cambios a través de HTTP

Pedro Vicente
fuente
0

Aquí está la definición de un repositorio simple de gitglossary :

Un repositorio simple es normalmente un directorio con el nombre apropiado con un sufijo .git que no tiene una copia extraída localmente de ninguno de los archivos bajo control de revisión. Es decir, todos los archivos administrativos y de control de Git que normalmente estarían presentes en el subdirectorio .git oculto están directamente presentes en el directorio repository.git, y no hay otros archivos presentes y desprotegidos. Por lo general, los editores de repositorios públicos ponen a disposición repositorios desnudos.

Llegué aquí porque estaba jugando con un "repositorio local" y quería poder hacer lo que quisiera como si fuera un repositorio remoto. Solo estaba jugando, tratando de aprender sobre git. Asumiré que esta es la situación para quien quiera leer esta respuesta.

Me encantaría que un dictamen pericial o algunos contraejemplos específicos, sin embargo, parece que (después de hurgar en algún código fuente de Git que he encontrado) simplemente ir al archivo .git/configy establecer el núcleo de atributos al descubierto al verdadero , Git le permitirá hacer lo que sea desea hacer al repositorio de forma remota. Es decir, las siguientes líneas deberían existir en.git/config :

[core]
    ...
    bare = true
...

(Esto es aproximadamente lo que el comando git config --bool core.bare true hará , que probablemente se recomienda para hacer frente a situaciones más complicadas)

Mi justificación para esta afirmación es que, en el código fuente de git, parece haber dos formas diferentes de probar si un repositorio está vacío o no. Una es al verificar una variable global is_bare_repository_cfg. Esto se establece durante alguna fase de configuración de la ejecución y refleja el valor encontrado en el .git/configarchivo. El otro es una función is_bare_repository(). Aquí está la definición de esta función:

int is_bare_repository(void)
{
    /* if core.bare is not 'false', let's see if there is a work tree */
    return is_bare_repository_cfg && !get_git_work_tree();
} 

No tengo el tiempo ni la experiencia para decir esto con absoluta confianza, pero por lo que pude decir si tiene el bareconjunto de atributos que trueen .git/configesto siempre debe devolver 1. El resto de la función probablemente sea para la siguiente situación:

  1. core.bare no está definido (es decir, ni verdadero ni falso)
  2. No hay árbol de trabajo (es decir, el subdirectorio .git es el directorio principal)

Experimentaré con él cuando pueda más tarde, pero esto parecería indicar que configurar core.bare = true es equivalente a eliminar core.bare del archivo de configuración y configurar los directorios correctamente.

En cualquier caso, configurar core.bare = true ciertamente le permitirá avanzar, pero no estoy seguro de si la presencia de archivos de proyecto hará que algunas otras operaciones salgan mal. Es interesante y supongo que es instructivo ir al repositorio y ver qué sucedió localmente (es decir, ejecutar git statusy dar sentido a los resultados).

Nathan Chappell
fuente
-1

Primero, backuptu repositorio existente:

(a)  mkdir backup

(b)  cd backup

(c)  git clone non_bare_repo

En segundo lugar, ejecute lo siguiente:

git clone --bare -l non_bare_repo new_bare_repo
Shaks
fuente
¿Para qué sirve el clon intermedio?
Stabledog
-4

Oneliner por hacer todas las operaciones anteriores:

for i in `ls -A .`; do if [ $i != ".git" ]; then rm -rf $i; fi; done; mv .git/* .; rm -rf .git; git config --bool core.bare true

(no me culpes si algo explota y no tienes copias de seguridad: P)

Tarmo
fuente
-9

Wow, es simplemente sorprendente cuántas personas intervinieron en esto, especialmente teniendo en cuenta que no parece que ninguno se haya detenido a preguntar por qué esta persona está haciendo lo que está haciendo.

La ÚNICA diferencia entre un repositorio git desnudo y no desnudo es que la versión no desnuda tiene una copia de trabajo. La razón principal por la que necesitaría un repositorio simple es si desea ponerlo a disposición de un tercero, en realidad no puede trabajar directamente en él, por lo que en algún momento tendrá que clonarlo en ese momento de vuelta a una versión de copia de trabajo normal.

Dicho esto, para convertir a un repositorio simple, todo lo que tiene que hacer es asegurarse de que no tiene compromisos pendientes y luego simplemente:

rm -R * && mv .git/* . && rm -R .git

Ahí tienes, repositorio desnudo.

Justin Buser
fuente
11
Esto no lo hará lo suficientemente desnudo. Intenta empujarlo. Necesitas hacer git config core.bare truelo mismo.
Antony Hatchkins
No voté en contra, pero solo quería señalar que la primera parte de esta respuesta que explica por qué querría un repositorio desnudo frente a uno no desnudo está bien , aunque no contiene suficientes detalles técnicos y puede ser un poco impreciso Sin embargo , para la segunda parte de su respuesta, si bien esos comandos configuran su repositorio para que esté vacío, Anthony tiene razón , aún debe configurarlo git config core.bare true, al igual que en esta respuesta .