Solución:
Git
Esta respuesta incluye GitHub, ya que muchas personas también han preguntado sobre eso.
Repositorios locales
Git (localmente) tiene un directorio (.git
) en el que envías tus archivos y este es tu ‘repositorio local’. Esto es diferente de los sistemas como SVN donde se agrega y se compromete con el repositorio remoto de inmediato.
Git almacena cada versión de un archivo que cambia al guardar el archivo completo. También es diferente de SVN en este sentido, ya que podría ir a cualquier versión individual sin ‘recrearla’ a través de cambios delta.
Git no ‘bloquea’ archivos en absoluto y, por lo tanto, evita la funcionalidad de ‘bloqueo exclusivo’ para una edición (me vienen a la mente sistemas más antiguos como pvcs), por lo que todos los archivos siempre se pueden editar, incluso cuando están fuera de línea. De hecho, hace un trabajo increíble al fusionar los cambios de archivos (¡dentro del mismo archivo!) Juntos durante las extracciones o recuperaciones / empujes a un repositorio remoto como GitHub. La única vez que necesita hacer cambios manuales (en realidad, editar un archivo) es si dos cambios involucran la misma línea (s) de código.
Sucursales
Las ramas le permiten conservar el código principal (la rama ‘maestra’), hacer una copia (una nueva rama) y luego trabajar dentro de esa nueva rama. Si el trabajo lleva un tiempo o el maestro recibe muchas actualizaciones desde que se realizó la rama, entonces se debe fusionar o reajustar (a menudo se prefiere para un mejor historial y más fácil de resolver conflictos) contra la rama maestra. Cuando haya terminado, vuelva a fusionar los cambios realizados en la rama en el repositorio principal. Muchas organizaciones utilizan ramas para cada trabajo, ya sea una característica, un error o un elemento de tarea. Otras organizaciones solo usan sucursales para cambios importantes, como actualizaciones de versiones.
Bifurcación: con una bifurcación usted controla y administra la bifurcación, mientras que con una bifurcación otra persona controla la aceptación del código de nuevo.
En términos generales, existen dos enfoques principales para realizar sucursales. La primera es mantener la mayoría de los cambios en la rama maestra, usando solo ramas para cosas más grandes y de mayor duración, como cambios de versión, donde desea tener dos ramas disponibles para diferentes necesidades. El segundo es mediante el cual básicamente crea una rama para cada solicitud de función, corrección de errores o tarea y luego decide manualmente cuándo fusionar esas ramas en la rama principal principal. Aunque esto suena tedioso, este es un enfoque común y es el que actualmente uso y recomiendo porque mantiene la rama maestra más limpia y es la maestra que promovemos a producción, por lo que solo queremos código completo y probado, a través del rebase y fusión de ramas.
La forma estándar de llevar una rama a la maestría es hacer una merge
. Las ramas también se pueden “rebasar” para “limpiar” el historial. No afecta el estado actual y se hace para dar un historial ‘más limpio’.
Básicamente, la idea es que se ramificó desde un cierto punto (generalmente desde el maestro). Desde que se ramificó, el ‘maestro’ en sí mismo se ha movido hacia adelante desde ese punto de ramificación. Será más ‘limpio’ (más fácil de resolver los problemas y el historial será más fácil de entender) si todos los cambios que ha realizado en una rama se comparan con el estado actual del maestro con todos sus últimos cambios. Entonces, el proceso es: guardar los cambios; obtenga el ‘nuevo’ maestro, y luego vuelva a aplicar (esta es la parte de rebase) los cambios nuevamente contra eso. Tenga en cuenta que la reorganización, al igual que la fusión, puede generar conflictos que debe resolver manualmente (es decir, editar y corregir).
Una pauta a tener en cuenta:
¡Solo vuelva a establecer la base si la rama es local y aún no la ha enviado a remota!
Esto se debe principalmente a que el rebase puede alterar el historial que ven otras personas, lo que puede incluir sus propias confirmaciones.
Seguimiento de ramas
Estas son las ramas que se nombran origin/branch_name
(en contraposición a solo branch_name
). Cuando empuja y extrae el código hacia / desde repositorios remotos, este es en realidad el mecanismo a través del cual sucede. Por ejemplo, cuando tu git push
una rama llamada building_groups
, tu rama va primero a origin/building_groups
y luego eso va al repositorio remoto. Del mismo modo, si haces un git fetch building_groups
, el archivo que se recupera se coloca en su origin/building_groups
rama. A continuación, puede optar por fusionar esta rama en su copia local. Nuestra práctica es hacer siempre un git fetch
y una combinación manual en lugar de solo una git pull
(que hace las dos cosas anteriores en un solo paso).
Buscando nuevas ramas.
Obteniendo nuevas ramas: En el punto inicial de un clon tendrás todas las ramas. Sin embargo, si otros desarrolladores agregan ramas y las envían al control remoto, debe haber una forma de ‘saber’ sobre esas ramas y sus nombres para poder desplegarlas localmente. Esto se hace a través de un git fetch
que obtendrá todas las ramas nuevas y cambiadas en el repositorio local utilizando las ramas de seguimiento (por ejemplo, origin/
). Una vez fetch
ed, uno puede git branch --remote
para enumerar las ramas de seguimiento y git checkout [branch]
para cambiar a cualquiera.
Fusión
La fusión es el proceso de combinar cambios de código de diferentes ramas o de diferentes versiones de la misma rama (por ejemplo, cuando una rama local y una remota no están sincronizadas). Si uno ha desarrollado un trabajo en una sucursal y el trabajo está completo, listo y probado, entonces se puede fusionar en el master
rama. Esto es hecho por git checkout master
para cambiar a la master
rama, entonces git merge your_branch
. La fusión traerá todos los archivos diferentes y incluso diferentes cambios en los mismos archivos juntos. Esto significa que realmente cambiará el código dentro de los archivos para fusionar todos los cambios.
Al hacer el checkout
de master
también se recomienda hacer un git pull origin master
para obtener la última versión del maestro remoto combinado con su maestro local. Si el maestro remoto cambió, es decir, moved forward
, verá información que refleja que durante ese git pull
. Si ese es el caso (maestro cambiado) se le aconseja que git checkout your_branch
y luego rebase
para dominarlo para que sus cambios se ‘reproduzcan’ en la parte superior del ‘nuevo’ maestro. Luego, continuaría actualizando el maestro como se muestra en el siguiente párrafo.
Si no hay conflictos, master tendrá los nuevos cambios agregados. Si hay conflictos, esto significa que los mismos archivos tienen cambios alrededor de líneas similares de código que no puede fusionar automáticamente. En este caso git merge new_branch
informará que hay conflictos que resolver. Los ‘resuelve’ editando los archivos (que tendrán ambos cambios en ellos), seleccionando los cambios que desea, eliminando literalmente las líneas de los cambios que no desea y luego guardando el archivo. Los cambios están marcados con separadores como ========
y <<<<<<<<
.
Una vez que haya resuelto cualquier conflicto, volverá a git add
y git commit
esos cambios para continuar la fusión (recibirás comentarios de git durante este proceso para guiarte).
Cuando el proceso no funciona bien, encontrará que git merge --abort
es muy útil para restablecer las cosas.
Reajustar y aplastar / reordenar / eliminar confirmaciones interactivas
Si ha realizado el trabajo en muchos pasos pequeños, por ejemplo, confirma código como 'trabajo en progreso' todos los días, es posible que desee 'aplastar' esas muchas confirmaciones pequeñas en algunas confirmaciones más grandes. Esto puede resultar especialmente útil cuando desee realizar revisiones de código con colegas. No desea reproducir todos los 'pasos' que tomó (a través de confirmaciones), solo quiere decir que aquí está el efecto final (diff) de todos mis cambios para este trabajo en una confirmación.
El factor clave a evaluar al considerar si hacer esto es si las múltiples confirmaciones están contra el mismo archivo o archivos más de una vez (es mejor aplastar las confirmaciones en ese caso). Esto se hace con la herramienta de reajuste interactivo. Esta herramienta te permite aplastar confirmaciones, eliminar confirmaciones, reformular mensajes, etc. Por ejemplo, git rebase -i HEAD~10
(nota: eso es un ~
, No un -
) muestra lo siguiente:
Sin embargo, tenga cuidado y use esta herramienta 'con cautela'. Haga un aplastamiento / eliminación / reorden a la vez, salga y guarde esa confirmación, luego vuelva a ingresar a la herramienta. Si las confirmaciones no son contiguas, puede reordenarlas (y luego aplastarlas según sea necesario). En realidad, también puede eliminar confirmaciones aquí, ¡pero realmente necesita estar seguro de lo que está haciendo cuando lo hace!
tenedores
Hay dos enfoques principales para la colaboración en los repositorios de Git. El primero, detallado anteriormente, es directamente a través de las ramas que las personas tiran y empujan desde / hacia. Estos colaboradores tienen sus claves SSH registradas en el repositorio remoto. Esto les permitirá enviar directamente a ese repositorio. La desventaja es que debes mantener la lista de usuarios. El otro enfoque, la bifurcación, permite a cualquiera "bifurcar" el repositorio, básicamente haciendo una copia local en su propia cuenta de repositorio Git. Luego pueden hacer cambios y, cuando terminan, enviar una 'solicitud de extracción' (en realidad, es más una 'solicitud' de ellos y una solicitud de 'extracción' para el mantenedor del repositorio real) para que se acepte el código.
Este segundo método, utilizando horquillas, no no requerir que alguien mantenga una lista de usuarios para el repositorio.
GitHub
GitHub (un repositorio remoto) es una fuente remota a la que normalmente empuja y extrae esos cambios confirmados si tiene (o se agrega a) dicho repositorio, por lo que local y remoto son en realidad bastante distintos. Otra forma de pensar en un repositorio remoto es que es un .git
estructura de directorio que vive en un servidor remoto.
Cuando 'bifurque' - en la GUI del navegador web de GitHub puede hacer clic en este botón - crea una copia ('clon') del código en tu Cuenta de GitHub. Puede ser un poco sutil la primera vez que lo haces, así que sigue asegurándote de mirar en qué repositorio se encuentra una base de código, ya sea el propietario original o 'bifurcado' y tú, por ejemplo, así:
Una vez que tenga la copia local, puede realizar los cambios que desee (tirando de ellos y empujándolos a una máquina local). Cuando haya terminado, envíe una 'solicitud de extracción' al propietario / administrador del repositorio original (suena elegante, pero en realidad solo hace clic en esto: ) y lo 'jalan'.
Lo más común para un equipo que trabaja en código es "clonar" el repositorio (haga clic en el icono "copiar" en la pantalla principal del repositorio). Luego, escriba localmente git clone
y pegar. Esto lo configurará localmente y también puede presionar y tirar a la ubicación (compartida) de GitHub.
Clones
Como se indica en la sección sobre GitHub, un clon es una copia de un repositorio. Cuando tiene un repositorio remoto, emite el git clone
comando contra su URL y luego terminará con una copia local, o clon, del repositorio. Este clon tiene todo, los archivos, la rama maestra, las otras ramas, todas las confirmaciones existentes, todo el asunto. Es este clon contra el que haces tus adiciones y confirmaciones y luego el repositorio remoto en sí es a lo que empujas esas confirmaciones. Es este concepto local / remoto lo que hace que Git (y sistemas similares a él, como Mercurial), sea un DVCS (Repartido Version Control System) a diferencia de los CVS (sistemas de control de versiones de código) más tradicionales, como SVN, PVCS, CVS, etc., donde se compromete directamente con el repositorio remoto.
Visualización
La visualización de los conceptos básicos se puede ver en
http://marklodato.github.com/visual-git-guide/index-en.html y
http://ndpsoftware.com/git-cheatsheet.html#loc=index
Si desea una visualización visual de cómo están funcionando los cambios, no puede vencer a la herramienta visual gitg
(gitx
para macOS) con una GUI que llamo 'el mapa del metro' (especialmente el metro de Londres), excelente para mostrar quién hizo qué, cómo cambian las cosas, se separaron y se fusionaron, etc.
¡También puede usarlo para agregar, confirmar y administrar sus cambios!
Aunque gitg / gitx es bastante mínimo, la cantidad de herramientas GUI continúa expandiéndose. Muchos usuarios de Mac usan la bifurcación de gitx de brotherbard y para Linux, una gran opción es smart-git con una interfaz intuitiva pero poderosa:
Tenga en cuenta que incluso con una herramienta GUI, probablemente ejecutará muchos comandos en la línea de comandos.
Para esto, tengo los siguientes alias en mi ~/.bash_aliases
archivo (que se llama desde mi ~/.bashrc
archivo para cada sesión de terminal):
# git
alias g='git status'
alias gcob='git checkout -b '
alias gcom='git checkout master'
alias gd='git diff'
alias gf='git fetch'
alias gfrm='git fetch; git reset --hard origin/master'
alias gg='git grep '
alias gits='alias | grep "^alias g.*git.*$"'
alias gl='git log'
alias gl1='git log --oneline'
alias glf='git log --name-status'
alias glp='git log -p'
alias gpull='git pull '
alias gpush='git push '
Y tengo los siguientes "alias de git" en mi ~/.gitconfig
archivo - ¿por qué tener estos?
¡Así que la finalización de la rama (con la tecla TAB) funciona!
Entonces estos son:
[alias]
co = checkout
cob = checkout -b
Uso de ejemplo: git co [branch]
<- La finalización de tabulación para las ramas funcionará.
Herramienta de aprendizaje GUI
Puede encontrar https://learngitbranching.js.org/ útil para aprender algunos de los conceptos básicos. Captura de pantalla:
Video: https://youtu.be/23JqqcLPss0
¡Finalmente, 7 salvavidas clave!
-
Usted hace cambios, los agrega y los confirma (pero no presione) y luego ¡oh! te das cuenta de que estás en maestro!
git reset [filename(s)] git checkout -b [name_for_a_new_branch] git add [file(s)] git commit -m "A useful message" Voila! You've moved that 'master' commit to its own branch !
-
Usted estropea algunos archivos mientras trabaja en una sucursal local y simplemente quiere volver a lo que tenía la última vez que hizo una
git pull
:git reset --hard origin/master # You will need to be comfortable doing this!
-
Comienzas a hacer cambios localmente, editas media docena de archivos y luego, oh mierda, todavía estás en la rama maestra (u otra):
git checkout -b new_branch_name # just create a new branch git add . # add the changes files git commit -m"your message" # and commit them
-
Usted estropea un archivo en particular en su rama actual y básicamente quiere 'restablecer' ese archivo (perder cambios) a cómo era la última vez que lo sacó del repositorio remoto:
git checkout your/directories/filename
En realidad, esto restablece el archivo (como muchos comandos de Git, no tiene un nombre adecuado por lo que está haciendo aquí).
-
Realiza algunos cambios localmente, quiere asegurarse de no perderlos mientras hace un
git reset
orebase
: A menudo hago una copia manual de todo el proyecto (cp -r ../my_project ~/
) cuando no estoy seguro de si podría equivocarme en Git o perder cambios importantes. -
Estás reajustando pero las cosas se complican:
git rebase --abort # To abandon interactive rebase and merge issues
-
Agregue su rama de Git a su
PS1
indicador (consulte https://unix.stackexchange.com/a/127800/10043), p. ej.La rama es
selenium_rspec_conversion
.
Un clon es simplemente una copia de un repositorio. En la superficie, su resultado es equivalente a svn checkout
, donde descarga el código fuente de algún otro repositorio. La diferencia entre VCS centralizados como Subversion y DVCS como Git es que en Git, cuando clonas, en realidad estás copiando todo el repositorio de origen, incluido todo el historial y las ramas. Ahora tiene un nuevo repositorio en su máquina y cualquier confirmación que realice irá a ese repositorio. Nadie verá ningún cambio hasta que envíe esas confirmaciones a otro repositorio (o al original) o hasta que alguien extraiga las confirmaciones de su repositorio, si es de acceso público.
Una rama es algo que está dentro de un repositorio. Conceptualmente, representa un hilo de desarrollo. Por lo general, tiene una rama maestra, pero también puede tener una rama en la que esté trabajando en alguna función xyz y otra para corregir el error abc. Cuando haya verificado una rama, las confirmaciones que realice permanecerán en esa rama y no se compartirán con otras ramas hasta que las fusione o las vuelva a establecer en la rama en cuestión. Por supuesto, Git parece un poco extraño cuando se trata de ramas hasta que miras el modelo subyacente de cómo se implementan las ramas. En lugar de explicarlo yo mismo (ya he dicho demasiado, creo), lo vincularé a la explicación de "informática" de cómo Git modela las ramificaciones y confirmaciones, tomada del sitio web de Git:
http://eagain.net/articles/git-for-computer-scientists/
Una bifurcación no es un concepto de Git en realidad, es más una idea política / social. Es decir, si algunas personas no están satisfechas con la forma en que se desarrolla un proyecto, pueden tomar el código fuente y trabajar en él por sí mismos por separado de los desarrolladores originales. Eso se consideraría una bifurcación. Git facilita la bifurcación porque todos ya tienen su propia copia "maestra" del código fuente, por lo que es tan simple como cortar lazos con los desarrolladores del proyecto original y no requiere exportar el historial desde un repositorio compartido como podría tener que hacer con SVN .
EDITAR: dado que no estaba al tanto de la definición moderna de "bifurcación" utilizada por sitios como GitHub, eche un vistazo a los comentarios y también a la respuesta de Michael Durrant debajo de la mía para obtener más información.
Aquí está la imagen de Oliver Steele de cómo encaja todo: