2009-08-15 15 views
64

¿Es posible en git pasar a otra rama sin verificar todos los archivos? Después de cambiar de rama, necesito eliminar todos los archivos, regenerarlos, confirmar y volver a abrir. Por lo tanto, revisar archivos es una pérdida de tiempo (y hay aproximadamente 14000 archivos, es una operación larga).switch git branch sin archivos checkout

para que todo sea claro:

necesito todo esto para cargar documentation a GitHub.

Tengo un repo con la rama gh-pages. Cuando reconstruyo la documentación localmente, la copio al directorio repo, commit y push a github. Pero no estaba contento porque tenía dos copias de la documentación a nivel local. Y decidí crear una rama vacía y después de activar el interruptor para vaciar y eliminar archivos. Pero volver atrás es una operación larga, así que hice esta pregunta.

sé que solo puedo dejar de GH-páginas rama y eliminar archivos, pero no me gustan los árboles de trabajo sucias)

+0

¿Cuánto tiempo es "largo" para usted? ¿En qué plataforma estás trabajando? ¿Estás trabajando en una red como NFS u otro tipo de intercambio de archivos? –

+0

¿Cuál es el propósito de este ejercicio? ¿Desea tener dos ramas, una con confirmaciones detalladas, y la segunda registrar solo cambios importantes (de grano grueso)? –

+0

Quizás es más barato crear un clon temporal (¿o permanente?) De su copia de trabajo. [Mi respuesta relacionada] (http://stackoverflow.com/a/29616287/946850) y un [writeup] (http://krlmlr.github.io/git-subbranch) muestran cómo funciona esto incluso como un subdirectorio del repositorio principal – krlmlr

Respuesta

70

Sí, puedes hacer esto.

git symbolic-ref HEAD refs/heads/otherbranch 

Si tiene que comprometerse en esta rama, tendrá que restablecer el índice demasiado de lo contrario va a terminar cometiendo algo basado en la última rama desprotegido.

git reset 
+0

Use 'echo" ebff34ffb665de0694872dceabe0edeaf50ec5a9 "> .git/HEAD' seguido de' git reset' para señalar una referencia en lugar de una rama. – cadorn

+1

Escribir directamente en el archivo HEAD es menos confiable. ¿Qué pasa si estás en un subdirectorio? Para cabeza separada (cabeza apuntando a SHA1 directamente), intente esto: 'git update-ref HEAD refs/heads/otherbranch' –

+2

Si desea consultar una nueva rama de la sucursal actual, otra forma de hacerlo es 1. 'git stash' 2.' git checkout -b otherBranch' 3. 'git pop' alijo – Winny

8

puede sobrescribir el archivo de HEAD con un nombre de rama diferente:

echo "ref: refs/heads/MyOtherBranch"> .git/HEAD

+13

Probablemente sea mejor usar el comando symbolic-ref para hacer esto por usted: 'git symbolic-ref HEAD refs/heads/MyOtherBranch' http://www.kernel.org/pub/software/scm/git/docs/git -symbolic-ref.html –

+0

@GregHewgill, esta es la única forma que conozco de mover la CABEZA a un hash de confirmación. ¿Puedes hacer eso con 'git symbolic-ref'? – tomekwi

7

Creo que está buscando el comando de fontanería git read-tree. Esto actualizará el índice pero no actualizará ningún archivo en su directorio de trabajo. Por ejemplo, suponiendo branch es el nombre de la rama a leer:

git read-tree branch

Si desea continuación, comprometerse con la rama que acaba de leer, también necesitará:

git symbolic-ref HEAD refs/heads/branch
+0

no Solo necesito cambiar de rama, no hay ningún otro cambio, así que symbolic-ref es lo suficientemente bueno – tig

0

Con tantos archivos, es mejor que solo conserve dos repositorios, uno para cada sucursal. Puede hacer cambios hacia adelante y hacia atrás según sea necesario. Esto va a ser menos sorprendente que tratar de jugar trucos escorbuto con git.

+0

Puedes usar 'git-new-worktree' para eso (en' contrib/') –

+0

Ah sí, para cada problema, git tiene una nueva característica ... –

+0

A menudo hice algo similar, que es copiar mi directorio local antes de hacer cualquier "cosa de git de miedo" como novato (como cambiar de rama, etc.). Animaría a la gente a ir por esa ruta hasta que se sienta seguro de su git-fu, pero alejarse de ella cuando sea posible. Mantener dos repositorios distintos está bien, pero agrega una capa de complicación y no le permite aprovechar las muchas funciones útiles de git (fusión, selección de cerezas, etc.). – David

14

¿No sería una mejor solución tener dos directorios de trabajo (dos áreas de trabajo) con un repositorio, o incluso dos repositorios?

Hay git-new-workdir herramienta en la sección contrib/ para ayudarte con esto.

+0

+1 No sabía nada de eso, gracias – MBO

+0

¿Es git-new-workdir lo mismo que el comando worktree de git? Utilizo worktree cuando quiero registrar una rama en una carpeta diferente (sin tener que clonar todo el repositorio). – Ryuu

+0

El script 'git-new-worktree' es anterior al subcomando' git worktree'; este comando no estaba disponible cuando se escribió la respuesta. El script, por ejemplo, requiere soporte de enlace simbólico; En mi humilde opinión, es mejor usar soporte nativo. –

0

Si simplemente está tratando de cambiar la ubicación de una derivación remota, puede hacerlo con "git push" sin tocar su copia local.

http://kernel.org/pub/software/scm/git/docs/git-push.html

El formato de un refspec <> parámetro es un signo opcional +, seguido de la fuente src ref <>, seguido de dos puntos:, seguido por el árbitro con destino < dst>. Se utiliza para especificar con qué objeto < src> se actualizará < dst> ref en el repositorio remoto.

por ejemplo, para actualizar foo para cometer c5f7eba haga lo siguiente:

git push origin c5f7eba:foo 

No estoy seguro si eso es lo que fueron después o no.

+0

La pregunta ya obtuvo una respuesta: http://stackoverflow.com/questions/1282639/switch-git-branch-without-files-checkout/1282706#1282706 – tig

24

Usando git comandos básicos solamente:

Esta respuesta es un poco más largo que el de Carlos, pero se compone exclusivamente de los comandos básicos de Git que puedo entender y por lo tanto recordar, lo que elimina la necesidad de seguir buscando lo arriba.

marcar la ubicación actual (confirmación primero si es necesario):

git checkout -b temp 

RESET (movimientos) el marcador a la otra rama sin cambiar directorio de trabajo:

git reset <branch where you want to go> 

ahora temporal y otra rama punto a la misma confirmación, y su directorio de trabajo está intacto.

git checkout <branch where you want to go> 

desde la cabeza ya está apuntando a la misma cometer, directorio de trabajo no se toca

git branch -d temp 

Tenga en cuenta que estos comandos también están disponibles desde cualquier cliente gráfico.

+3

Preferiría 'git reset --soft 'para evitar actualizar el índice – JoelFan

+6

Estoy de acuerdo con su estrategia de evitar los comandos de git plomería y favorecer a los de porcelana. – user64141

0

puede hacer uso de

 1. git checkout -f <new-branch> 
     2. git cherry-pick -x <previous-branch-commit-id> 

anterior-rama-commit-id es la confirmación desde la que desea copiar los datos de edad.

3

Para beneficio del lector:

Si bien creo que es una Charles Bailey's solution correcta, esta solución necesita un pellizco cuando se cambia a algo, que no es una sucursal local. También debería haber alguna forma de hacerlo con comandos regulares, lo cual es fácil de entender. Esto es lo que ocurrió:

git checkout --detach 
git reset --soft commitish 
git checkout commitish 

Explicación:

  • git checkout --detach es lo mismo que git checkout HEAD^{} que deja detrás de la rama actual y entra en "estado de cabeza separada". Por lo tanto, la siguiente modificación de HEAD ya no afecta a ninguna rama. Separar HEAD no afecta al árbol de trabajo ni al índice.
  • git reset --soft commitish luego mueve HEAD al SHA del commitish dado. Si también desea actualizar el índice, deje --soft, pero no lo recomiendo. Esto, una vez más, no toca el árbol de trabajo, y (--soft) no el índice.
  • git checkout commitish luego conecta HEAD a la dada commitish (rama) de nuevo. (Si commitish es un SHA, no ocurre nada.) Esto tampoco afecta al índice ni al árbol de trabajo.

Esta solución acepta todo lo que se refiere a una confirmación, por lo que es ideal para algunos alias git. El rev-parse a continuación es solo una prueba para asegurarse, nada se rompe en la cadena, de modo que los errores tipográficos no cambian accidentalmente al estado principal separado (la recuperación de errores sería mucho más compleja).

Esto lleva a la siguiente git switch treeish alias:

git config --global alias.switch '!f() { git rev-parse --verify "$*" && git checkout "HEAD^{}" && git reset --soft "$*" && git checkout "$*"; }; f' 

su información, usted lo puede encontrar en mi lista de git aliases.

+0

Enfoque interesante. +1 – VonC

+0

Muy útil. ¡Gracias! –