2008-10-26 14 views
9

Tengo un repositorio Git local en el que he estado desarrollando durante unos días: tiene dieciocho confirmaciones hasta ahora. Esta noche, creé un repositorio privado de Github al que esperaba presionarlo; sin embargo, cuando lo hice, solo terminó presionando ocho de los dieciocho compromisos contra Github. Eliminé el repositorio de Github y lo volví a intentar, con el mismo resultado.Al enviar un repositorio de Git existente a Github solo se envía la mitad de las confirmaciones?

¿Alguna idea de por qué esto podría estar pasando? He hecho este procedimiento antes sin algunas veces con éxito, así que estoy un poco perplejo.

Actualización: Hay, y siempre ha habido, solo la rama principal en este repositorio. Solo para abordar algunas de las respuestas publicadas ...

Respuesta

17

Me tomó un vistazo al repositorio en cuestión y esto es lo que estaba pasando:

  • En algún momento, RPJ habían realizado git checkout [commit id]. Esta CABEZA apuntada en un compromiso suelto en lugar de una rama reconocida. Creo que este es el problema de la "CABEZA colgando" al que se refiere CesarB.
  • Sin darse cuenta de este problema, él siguió haciendo cambios y comprometiéndolos, lo que golpeó HEAD cada vez. Sin embargo, HEAD solo apuntaba a una cadena de confirmaciones pendiente, no a una rama reconocida.
  • Cuando fue a presionar sus cambios, git empujó todo a la parte superior del maestro, que estaba a la mitad del árbol actual en el que estaba.
  • La confusión se produjo

Este diagrama debe hacerlo más claro:

    -- D -- E -- F 
       /   ^
    A -- B -- C -    | 
^  ^    HEAD 
    |   | 
remote master 

Cuando trató de empujar sus cambios, sólo se A través Cremote fueron empujadas y se trasladó hasta el C. No pudo obtener commits D hasta F para presionar porque no están referenciados por una rama conocida.

Esto es lo que se ve cuando estás en este estado:

$ git branch 
* (no branch) 
master 

La solución es mover master hasta F en la cadena colgando de confirmaciones. Así es como lo hice.

  • crear una rama legítima para el estado actual:

    git checkout -b tmp

    • La rama tmp ahora apunta a cometer F en el diagrama anterior
  • de avance rápido master a tmp

    git checkout master

    git merge tmp

    • master ahora apunta a cometer F.
  • de deshacerse de su rama temporal

    git branch -d tmp

  • Puede felices para empujar al repositorio remoto y se debe enviar todos los cambios.

+0

Este enfoque está bien si quiere tener cuidado; si * sabe * que la fusión va a avanzar rápidamente, entonces puede simplemente eliminar y volver a crear la rama. Ver mi respuesta –

+0

Tienes razón, si no es un avance rápido terminarás con un árbol ligeramente diferente, pero igual obtendrás el mismo resultado final. Sin embargo, tu respuesta es mucho más simple. – farktronix

+0

no ayuda si tiene tenedores –

2

Supongo que lo primero que haría sería ejecutar git fsck en su repositorio local para asegurarme de que todo está en orden.

Nunca he visto este problema antes, y no puedo pensar en lo que podría estar mal.

3

Comprueba si estás presionando las ramas correctas, y que las ramas realmente tienen lo que crees que tienen. En particular, verifique si no tiene un HEAD separado, lo cual puede ser bastante confuso si no se lo hace a propósito.

La forma más fácil de comprobar es usar gitk --all, que muestra gráficamente todas las ramas, la CABEZA y más.

1

Entonces, resulta que ambos: el hash de confirmación en .git/refs/heads/master era correcto y la información en .git/logs/refs/heads/master estaba incompleta; en eso me refiero a que solo se envió e incluyó el hash de confirmación especificado en .git/refs/heads/master.

Una vez que arreglé estos archivos (a mano) y los devolví a Github, todo volvió a ser gravy. Todavía tengo ni idea qué pasó para conseguir cosas en este estado, pero estoy contento de haber resuelto al menos la solución.

En caso de que alguien se pregunte: para arreglar .git/refs/heads/master, acabo de reemplazar el contenido de ese archivo con el último hash de confirmación (HEAD), y para arreglar .git/logs/refs/heads/maestro, simplemente copié el contenido de .git/logs/HEAD en .git/logs/refs/heads/master. Easy peasy ... NO.

+0

Probablemente tenga, como mencioné en mi respuesta, una "CABEZA separada". Compruebe .git/HEAD; si NO tiene "ref: refs/heads/master" (u otra referencia: línea), tiene un HEAD separado, y sus confirmaciones no irán a ninguna rama, solo a HEAD. – CesarB

+0

Y, por cierto, si tiene un HEAD separado, solo solucionó los síntomas, y todos sus nuevos commits seguirán yendo solo al HEAD. IIRC, la forma de salir de esa situación es pagar una sucursal ("git checkout master"), que establecerá el HEAD para que apunte a esa rama. – CesarB

1

no tengo la reputación comentar directamente sobre la respuesta anterior de CesarB, pero gitk --all no funciona en este caso, ya que sólo las listas de las ramas conocidas.

gitk HEAD muestra este problema, pero no está del todo claro. El arma humeante es que master muestra el árbol de confirmación en lugar del compromiso más reciente.

5

De Git 1.7.3 en adelante, se puede hacer esto con un simple comando:

git checkout -B master 

El interruptor -b significa “crear sucursal aquí antes de comprobar hacia fuera” y -B es la versión incondicional de eso “ incluso si la sucursal ya existe, en ese caso, muévela aquí antes de echarle un vistazo ".


Un enfoque muy simple para solucionar este tipo de problema es simplemente eliminar la rama master y volver a crearla. Después de todo, las ramas en git son simplemente nombres para confirmaciones y la rama master no es nada especial.

Así que asumiendo que la corriente cometer es el que usted desea master a ser, sólo tiene que hacer

git branch -D master 

para eliminar el master rama existente, a continuación, haga

git checkout -b master 

a: a) crear una nueva rama llamada master que apunta a la confirmación actual yb) actualización HEAD para apuntar a la rama master. Después de eso, HEAD se adjuntará al master y por lo tanto master se moverá hacia adelante cada vez que confirme.

+0

Mi método preferido no implica la eliminación, solo la reasignación. 'git branch -f master' fuerza a la rama' master' existente para que apunte a su 'HEAD' actual, y luego 'git checkout master' lo saca del estado" colgado ". – Quuxplusone

+1

@Quuxplusone: con Gits recientes, incluso eso es más complicado de lo necesario: simplemente use 'checkout -B'. He actualizado mi respuesta. –

0

He tenido el mismo problema dos veces, y finalmente descubrí qué estaba causando. En el proceso de editar una confirmación antigua con git rebase -i, en lugar de llamar al git commit --amend, estaba llamando al git commit -a por la fuerza de la costumbre, seguido inmediatamente por git rebase --continue, por supuesto. Alguien más podría explicar lo que sucede detrás de escena, pero parece que el resultado es el problema HEAD separado.

Cuestiones relacionadas