¿Cómo crear una nueva (y vacía) rama "raíz"?

135

Me gustaría definir una nueva rama "raíz" en este repositorio de git. Por rama "raíz" me refiero a una rama que es completamente independiente de todas las otras ramas en el repositorio 1 .

Desafortunadamente, incluso el commit (llamémoslo A) en la base del árbol de commit del repositorio contiene muchos archivos (este fue un repositorio que se inicializó en un proyecto ya bastante maduro).

Esto significa que incluso si di Acomo la nueva rama <start-point>, esta nueva rama no comenzaría desde una "pizarra limpia", sino que contendría todos los archivos que se confirmaron A.

¿Hay alguna forma de que pueda crear una rama completamente desnuda en este repositorio, con la <start-point>mayor precisión Aposible?


1 Por cierto, esto no es equivalente a crear un nuevo repositorio. Los repositorios separados serían menos convenientes por muchas razones.


EDITAR : OK, esto es lo que hice, basado en la respuesta de vcsjones :

# save rev of the current earliest commit
OLDBASE=$(git rev-list --max-parents=0 HEAD)

# create a new orphan branch and switch to it
git checkout --orphan newbranch
# make sure it's empty
git rm -rf .

# create a new empty commit in the new branch, and
# save its rev in NEWBASE
git commit --allow-empty -m 'base commit (empty)'
NEWBASE=$(git rev-list HEAD)

# specify $NEWBASE as the new parent for $OLDBASE, and
# run filter-branch on the original branch
echo "$OLDBASE $NEWBASE" > .git/info/grafts
git checkout master
git filter-branch

# NOTE: this assumes that the original repo had only one
# branch; if not, a git-filter-branch -f <branch> command
# need to be run for each additional branch.

rm .git/info/grafts

Aunque este procedimiento es un poco complicado, el resultado final es una confirmación de base vacía que puede servir <start-point>para cualquier nueva "rama de pizarra limpia"; todo lo que necesito hacer es

git checkout -b cleanslate $(git rev-list --max-parents=0 HEAD)

En el futuro siempre crearé nuevos repositorios como este:

git init
git commit --allow-empty -m 'base commit (empty)'

... para que la primera confirmación esté vacía y siempre disponible para iniciar una nueva rama independiente. (Esta sería, lo sé, una instalación que rara vez se necesita, pero es bastante fácil ponerla a disposición).

kjo
fuente
1
@ Anonymoose: Solo para el registro (en lugar de debate): No estoy de acuerdo con tu opinión.
kjo
1
Parece que hay una solución mucho más simple basada en git rebase --onto, consulte stackoverflow.com/questions/645450/…
Stéphane Gourichon

Respuestas:

223

Use el --orphanal crear la rama:

git checkout --orphan YourBranchName

Esto creará una nueva rama con cero confirmaciones, sin embargo, todos sus archivos serán organizados. En ese punto, simplemente podría eliminarlos.
("eliminarlos": A git reset --hardvaciará el índice, dejándolo con un árbol de trabajo vacío)

Eche un vistazo a la página de manual para finalizar la compra para obtener más información sobre --orphan.

vcsjones
fuente
¿Esto esencialmente crea una pizarra en blanco? Como en, desde cero? ¿O mantiene todos sus cambios anteriores, pero simplemente no en el historial de git?
Con Antonakos
44
@ConAntonakos Esto crea una nueva rama sin un padre. Las otras ramas no se ven afectadas, todos sus cambios se mantienen.
fuz
11

Para agregar a la respuesta aceptada, la mejor práctica para volver al estado limpio es crear una confirmación vacía inicial para que pueda volver a redactar fácilmente mientras configura sus ramas para la posteridad. Además, dado que desea un estado limpio, probablemente haya confirmado archivos que no debería, por lo que debe eliminarlos del índice. Con los que tienes en mente deberías:

$ git checkout --orphan dev2
Switched to a new branch 'dev2'
$ git reset # unstage all the files, you probably don't want to commit all of them
$ git commit --allow-empty -m 'Initial empty commit'
[dev2 (root-commit) a515c28] Initial empty commit
Mr_and_Mrs_D
fuente
1
Creo que esto no es necesario a partir de 2012 porque puede volver a crear una base en la raíz .
Timmmm
1

Si usa git 2.23 o superior, puede estar acostumbrado git switchy engit restore lugar de git checkout. Si es así, la bandera es la misma que se menciona en esta respuesta .

git switch --orphan YourBranchHere
Capitán Hombre
fuente
1

¿Hay alguna forma de crear una rama completamente desnuda en este repositorio?

El comando real para usar (con Git 2.28+) es:

git switch --discard-changes --orphan newBranch
# or
git switch -f --orphan newBranch

git switchestá disponible en Git 2.23 (agosto de 2019) y reemplaza el antiguo git checkoutcomando confuso .

Pero recomendaría Git 2.28 (Q3 2020), porque git switch --discard-changes --orphanse ha optimizado en esa versión.

Ver commit 8d3e33d , commit 8186128 (21 de mayo de 2020) por brian m. carlson ( bk2204) .
(Fusionada por Junio ​​C Hamano - gitster- en commit ded44af , 09 jun 2020)

builtin/checkout: simplifica la inicialización de metadatos

Firmado por: brian m. carlson
Revisado por: Derrick Stolee

Cuando llamamos init_checkout_metadataen reset_tree,que queremos pasar el ID de objeto de una confirmación de que se trate de modo que se puede pasar a los filtros, o si no hay cometió, el árbol.

Anticipamos este último caso, que puede ocurrir en otra parte del código de pago, pero no puede ocurrir aquí.

El único caso en el que no tenemos un objeto de confirmación es cuando invocamos git switchcon --orphan.

Además, solo podemos acceder a esta ruta de código sin un objeto de confirmación adicionalmente con uno --forceo --discard-changes.

En tal caso, no tiene sentido inicializar los metadatos de pago con un commit o árbol porque

  • (a) no hay confirmación, solo el árbol vacío, y
  • (b) nunca utilizaremos los datos, ya que no se borrará ningún archivo al retirar una sucursal sin archivos.

Pase la ID del objeto todo ceros en este caso, ya que solo necesitamos algún valor que sea un puntero válido.

Prueba:

git switch master
echo foo >foo.txt
git switch --discard-changes --orphan new-orphan2
git ls-files >tracked-files
# test_must_be_empty tracked-files
VonC
fuente