¿Cómo convierto un repositorio git simple en uno normal (en el lugar)?


81

Tengo un repositorio git básico, pero necesito acceder y navegar por su contenido a través de ssh (en un administrador de archivos como la experiencia del usuario).

Supongo que podría clonarlo:

git clone -l <path_to_bare_repo> <new_normal_repo>

Sin embargo, mi repositorio tiene un tamaño de aproximadamente 20 GB y no tengo espacio para duplicarlo. ¿Hay alguna forma de convertir el repositorio básico en el lugar para terminar con una copia de trabajo en él?


5
No probado, pero si mueve, coloca el contenido del repositorio simple en un .gitdirectorio y establece el bareparámetro en la configuración en falso, debería comportarse como un repositorio normal donde puede git checkoutobtener sus archivos.
Noufal Ibrahim

Dependiendo de lo que quiera decir con "navegar por su contenido", probablemente pueda hacer todo lo que quiera en un repositorio simple usando git showygit cat-file
William Pursell

Gracias por la pista, útil. Sin embargo, necesito una experiencia más similar al administrador de archivos (edité la pregunta).
nyi

Si su sistema de archivos admite enlaces físicos y clona en el mismo sistema de archivos, clonar -l no ocupa más espacio en el disco porque enlaza todos los objetos. Sin embargo, necesitará espacio para la caja, como han señalado otros.
Neil Mayhew

1
Si su desnudo repositorio lleva hasta 20 GB de espacio en disco, ¿cuánto más la necesidad árbol de trabajo? ¿De verdad tienes tanto espacio?
ADTC

Respuestas:


113

Nota : Probé esto en un repositorio de 1 confirmación muy simple . Vuelva a verificar esto, lea las páginas de manual y siempre esté feliz de haber hecho una copia de seguridad antes de seguir los consejos que encontró en StackOverflow. (Retrocede, ¿verdad?)

Para convertir un --barerepositorio en uno no vacío:

  1. Cree una .gitcarpeta en el nivel superior de su repositorio.
  2. Mueva las cosas de administración del repositorio ( HEAD branches config description hooks info objects refsetc.) al .gitque acaba de crear.
  3. Ejecutar git config --local --bool core.bare falsepara convertir el repositorio de git local a non-bare.
  4. (a través del comentario de Tamás Pap ) Después del paso # 3, verá que está en la rama master(o cualquiera que sea su rama principal) y todos sus archivos se eliminan y la eliminación se realiza por etapas. Eso es normal. Simplemente pague manualmente master, o haga una git reset --hard, y ya está.
  5. (para resolver el problema informado por Royi ) Edite el .git/configarchivo agregando una línea fetch = +refs/heads/*:refs/remotes/origin/*después url = <...>en la [remote "origin"]sección. De git fetchlo contrario , no verá origin/masterlas ramas de otros orígenes.

Estos pasos van en la dirección opuesta a esta pregunta , "git-convert normal to bare repository"; en particular, tenga en cuenta esta respuesta , que establece que los pasos anteriores (en, supongo, en cualquier dirección) son diferentes de hacer a git-clone. Sin embargo, no estoy seguro de si eso es relevante para usted, pero lo mencionó git cloneen la pregunta.


2
Hice todo lo escrito, pero aún así, cuando envío archivos, no aparecen. ¿Qué podría ser (también cambié denyCurrentBranch para ignorar)?
Royi

¡Gracias! Llegué al trabajo un día y descubrí que mi repositorio principal, del que tenía varios árboles de trabajo en otros lugares, informaba que estaba "vacío". Todos los demás árboles de trabajo estaban bien. No tenía idea de cómo desvincularme, pero encontré esta respuesta y funcionó muy bien.
Davidbak

17

Tuve un escenario ligeramente diferente:

Solución:

  • clonar un repositorio vacío en ese contenido, en un .gitdirectorio:
    git clone --bare https://github.com/user/project .git
  • Márquelo como un repositorio no desnudo:
    git config --local --bool core.bare false
  • restablecer el índice (de lo contrario, se cree que todo ha sido eliminado, ya que un .git desnudo de recompra no incluye un archivo ' index'.)
    git reset HEAD -- .
    que restaura el .git/index.

He transformado efectivamente un repositorio simple en uno no desnudo, al tiempo que conservo el contenido que había obtenido anteriormente.
El guión completo que he estado usando durante años incluye los pasos:

cd /path/to/current/worktree

# That creates a .git directly at the right place
git clone --bare /url/of/repo .git

# restore the link between the local repo and its upstream remote repo
git config --local --bool core.bare false
git config --local remote.origin.fetch +refs/heads/*:refs/remotes/origin/*
git fetch origin
git branch -u origin/master master

# reset the index (not the working tree)
git reset HEAD -- .

Pero reconozco que la solución aceptada (con el paso útil git resetagregado por ADTC ) es más simple.


También vale la pena señalar que si el repositorio simple se creó en una máquina con diferentes finales de línea, es posible que aún vea archivos modificados incluso después de realizar estos pasos. Creo que eso es normal; git está intentando arreglar los cambios de línea. No estoy seguro de por qué.
Juno Woods

Entonces, ¿básicamente clonó un repositorio de GitHub como simple, cambió a no desnudo, colocó manualmente todo el archivo de su "no-repositorio" y restableció el índice? ¿En qué se diferencia de simplemente clonar el repositorio como non-bare en primer lugar? El proceso de clonación no desnuda comprobará todos los archivos de todos modos. Y si realmente lo desea, puede reemplazar los archivos extraídos con los de su "no repositorio".
ADTC

@ADTC el objetivo es obtener una .gitsubcarpeta en un árbol de trabajo (que sabe que es su repositorio) inicialmente hecha de un archivo (no git). No podría haber revisado un repositorio no desnudo, ya que la carpeta en la que estaba haciendo el pago no está vacía. Hacer el non-bare git clone --no-checkouten una subcarpeta me habría obligado a subir el .gitnivel. Hacer un clon desnudo me permitió crear directamente la .gitsubcarpeta donde la quería. Puede ver el guión aquí: github.com/VonC/compileEverything/blob/…
VonC

"No podría haber revisado un repositorio no desnudo, ya que la carpeta en la que estaba haciendo el pago no está vacía". ¿Quiere decir que tiene un árbol de trabajo que no es de Git que contiene cambios que aún no se han confirmado y que tiene la intención de confirmarlo después de haberlo convertido en un árbol de trabajo habilitado para Git? Sí, supongo, funciona para tal caso de uso. Personalmente, clonaría en una carpeta vacía y compararía las dos primero (usando una herramienta externa). Pero ese soy solo yo.
ADTC

@ADTC No: no tengo un "árbol de trabajo que no sea de git que contenga cambios que aún no se hayan confirmado". Yo no quiero comprometer nada. Lo que tengo es un árbol de trabajo exacto de un repositorio: todo lo que falta es su archivo .git. Obtengo la .gitcopia a través de un clon simple, transformo esa .gitcarpeta en una no desnuda y hago una git resetpara que git se dé cuenta de que el árbol de trabajo ya está allí. Eso es exactamente lo que hace github.com/VonC/compileEverything/blob/… .
VonC

11

Para simplificar y combinar la información en las respuestas:

Hay tres diferencias que hacen que un repositorio simple sea diferente de una carpeta .git normal:

  • core.bare se establece en verdadero en el archivo de configuración
  • el archivo de índice y el árbol de trabajo no existen
  • no se genera una especificación de referencia predeterminada para el control remoto "origen"

Entonces, simplemente puede mover su repositorio básico para que sea la subcarpeta .git de una nueva carpeta,

mkdir clone
mv bare.git clone/.git

Cambiar core.bare:

cd clone
git config --local --bool core.bare false

Agregue una especificación de referencia de origen predeterminada para realizar git fetchy git pushelegir los mismos valores predeterminados que de costumbre:

git config remote.origin.fetch '+refs/heads/*:refs/remotes/origin/*'

Y genere el archivo de índice y el árbol de trabajo:

git checkout master

Recomiendo en git checkoutlugar de git resetgenerar los archivos, en caso de que se ingrese accidentalmente en el lugar equivocado.


9

La pregunta del póster original es acerca de no tener suficiente espacio para hacer las cosas de manera simple. Para aquellos que tienen suficiente espacio, la respuesta es mucho más simple:

git clone foo.git foo

La razón por la que quiero evitar esto es cuando el repositorio se vuelve grande, el clon de git a veces muere. Quiero hacer un rsync del repositorio desnudo y luego convertirlo.
Sridhar Sarnobat

@SridharSarnobat, luego considere realizar las tareas descritas en la respuesta aceptada: stackoverflow.com/a/10637882/377270 - Pongo esta respuesta de una línea aquí para que las personas con suficiente espacio libre puedan hacer las cosas de manera fácil.
sarnold

6

Si tiene poco espacio en disco, será un problema expandir el árbol de trabajo convirtiéndolo en un repositorio normal, pero puede examinar el contenido de un repositorio sin convertirlo. Úselo git cat-file -p <commit-sha>en cualquier confirmación para ver el árbol al que se refiere. Úselo git cat-file -p <blob-sha>para ver el contenido del archivo al que hace referencia el blob. Use git show <sha>:pathdonde sha es una confirmación o un árbol para ver el contenido del blob en la ruta.


1
Tiene razón, pero necesito navegarlo de manera más conveniente (en un administrador de archivos sobre ssh). Por lo tanto, tendré que vivir con el mayor espacio en disco.
nyi

1
De hecho, este es un problema real (+1). Los árboles de trabajo suelen consumir hasta la mitad del espacio en disco; en parte porque las historias de git están comprimidas de forma agresiva.
jpaugh

3

cd en repositorio desnudo y hacer

  1. Ya sea:
git config core.bare false
git reset --hard
  1. o
git clone X.git X

(le dará un repositorio de git regular que se llama X)


Esta es la solución más simple y puedo confirmar en 2019 que funciona (el primer enfoque).
Sridhar Sarnobat

Solo una pequeña nota que había olvidado (que se aplica a todas las respuestas): deberá editar el archivo de configuración cuando presione por primera vez para establecer la URL remota.
Sridhar Sarnobat

2

Si no le importa trabajar en un árbol de trabajo diferente, entonces

git worktree add ../repo2
cd ..
git status # now works fine

Tenga en cuenta que esto no es un clon.


Esto es genial, no estoy seguro de por qué no está más arriba en la lista
Nickolai

0

Push-to-Deploy

En lugar de convertir el control remoto simple en un repositorio estándar, puede usar el script posterior a la recepción en el directorio de enlaces para expandir el repositorio en un directorio de implementación.

Este es un buen ejemplo de cómo configurar Push-to-Deploy

Para facilitar la referencia, este es el ejemplo del contenido del script del enlace anterior. Implementará solo empujes desde la rama "maestra" a un directorio llamado "implementación" que está en el mismo nivel que el directorio principal del repositorio:

#!/usr/bin/env ruby
# post-receive

# 1. Read STDIN (Format: "from_commit to_commit branch_name")
from, to, branch = ARGF.read.split " "

# 2. Only deploy if master branch was pushed
if (branch =~ /master$/) == nil
    puts "Received branch #{branch}, not deploying."
    exit
end

# 3. Copy files to deploy directory
deploy_to_dir = File.expand_path('../deploy')
`GIT_WORK_TREE="#{deploy_to_dir}" git checkout -f master`
puts "DEPLOY: master(#{to}) copied to '#{deploy_to_dir}'"
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.