Ahora que ya no le temes a GIT, aquí te mostramos cómo aprovechar lo que sabes

La primera parte de esta serie analizó el funcionamiento interno de GIT y le mostró cómo no tener miedo de trabajar con Git.

Ahora que entendemos cómo funciona Git, entremos en lo más sustancioso: cómo aprovechar lo que sabemos en nuestros proyectos.

Unir

Fusionar fusiona su código.

¿Recuerda cómo estábamos siguiendo las buenas prácticas de Git, teniendo ramas para varias funciones en las que estábamos trabajando y no para todo master? Llegará un momento en que haya terminado con esa función y querrá incluirla en su archivo master. Aquí es donde mergeentra en juego. Desea fusionar su rama en master.

Hay 2 tipos de fusiones:

Fusión de avance rápido

Volviendo a nuestro ejemplo de la última vez:

Esto es tan simple como mover la etiqueta de mastera the-ending. Git no tiene ninguna duda sobre lo que se necesita hacer exactamente, ya que nuestro "árbol" tenía una única lista de nodos enlazados.

$ git branch master * the-ending $ git checkout master Switched to branch 'master' $ git merge the-ending Updating a39b9fd..b300387 Fast-forward byeworld | 1 + 1 file changed, 1 insertion(+) create mode 100644 byeworld

Combinación de avance no rápido

Este es el tipo de fusión en la que Git no sabe qué hacer. Hay algunos cambios en la rama base, y algunos más en la rama que queremos fusionar, lo que resulta en conflictos de fusión aterradores .

Esto es lo primero que debe saber sobre los conflictos de fusión: Si no sabe lo que está sucediendo:

git merge --abort

Esto lo devolverá al estado original, sin efectos secundarios. Acabas de abortar el desastre que estabas a punto de hacer.

Veamos ahora paso a paso cómo resolver conflictos de fusión.

$ git checkout -b the-middle Switched to a new branch 'the-middle'

Continuando con nuestro estilo, aprendamos con un ejemplo. Modifico helloworlden rama the-middle.

$ git diff diff --git a/helloworld b/helloworld index a042389..e702052 100644 --- a/helloworld +++ b/helloworld @@ -1 +1,3 @@ hello world! + +Middle World

Agregar y comprometerse the-middle.

Luego, cambio mastery modifico helloworlden master. Agrego lo siguiente:

$ git diff --cached diff --git a/helloworld b/helloworld index a042389..ac7a733 100644 --- a/helloworld +++ b/helloworld @@ -1 +1,3 @@ hello world! + +Master World

¿Ves por qué tuve que hacer git diff --cachedaquí? Si no, ¡pregúntame a continuación!

¡Ahora es el momento de fusionarse!

$ git merge the-middle Auto-merging helloworld CONFLICT (content): Merge conflict in helloworld Automatic merge failed; fix conflicts and then commit the result.

Cuando mergefalla, esto es lo que hace git: modifica el archivo con la combinación para mostrarle exactamente sobre qué no puede decidir.

$ cat helloworld hello world!
$ cat helloworld hello world! <<<<<<>>>>>> the-middle

¿Esto tiene sentido? La <<<<< HEADparte es nuestra (la rama base) y la >>>>> the-middle partes theirs(la rama que se fusiona con la rama base).

Simplemente puede editar el archivo para eliminar las cosas adicionales agregadas por git y elegir lo que debe incluirse helloworldfinalmente. Hay algunas herramientas e integraciones de editor para facilitar esto, pero creo que saber cómo funciona debajo del capó te da más confianza cuando no tienes tu editor favorito por ahí.

$ git status On branch master You have unmerged paths. (fix conflicts and run "git commit") (use "git merge --abort" to abort the merge) Unmerged paths: (use "git add ..." to mark resolution) both modified: helloworld

Decidí quedarme con ambas partes.

$ cat helloworld hello world! Master World Middle World

Y ahí lo tienes:

$ git add helloworld $ git commit -m "resolve merge conflict" [master c747e68] resolve merge conflict

Mandos a distancia

Dado que un poder del control de la fuente de la versión es guardar su código en caso de desastres, los controles remotos están aquí para ayudar. Un control remoto es una copia alojada externamente de su repositorio git. Para ser más precisos, un control remoto es un repositorio externo (no necesariamente del mismo código que tiene). Por externo, podría estar en una carpeta diferente en su sistema o en la nube.

Clon

Clone clona el repositorio de forma remota en su directorio de trabajo actual. Esto es simplemente crear una copia de la .git/carpeta, que nos brinda el historial completo y los archivos necesarios para completar el directorio de trabajo.

git clone 

Si no ha clonado, probablemente no tenga un control remoto. Puedes crear un control remoto como este:

git remote add  

Empujar y jalar

Empujar y Tirar son acciones aplicadas en el remote.

Empujar empuja sus cambios al control remoto. ¡Entonces, estamos enviando el Indexy correspondiente Objectsdesde la tienda de objetos!

git push  

Pull extrae el código del control remoto. ¡Exactamente como antes, estamos copiando el Indexy correspondiente Objectsde la tienda de objetos!

git pull origin master

origines el nombre predeterminado del control remoto. Y puesto que masteres la rama por defecto, se puede ver cómo las recae comando en el nombre sencillo encontramos en todas partes: git pull origin master. Ahora lo sabes mejor.

Reiniciar

Restablecer restablece su base de código a una versión anterior. Reset viene con 3 banderas:

--soft, --hardY --mixed.

La belleza de reset, es poder cambiar la historia. Digamos que comete un error con a commit, y ahora git logtodo está arruinado con confirmaciones como:

Bugfix

Final BugFix

Final Final BugFix

God why isn't this working last try bug fix

Si desea mantener masterlimpio su historial, desea limpiar este registro de confirmación.

Si envía una solicitud de extracción donde no hay aplastamiento, ¡ellos también esperarán un historial de confirmaciones limpio!

Ahí es donde resetentra en juego: puede resettodas sus confirmaciones y convertirlas en una única confirmación:got sh*t done!

(No use esto como su mensaje de confirmación, ¡siga las mejores prácticas!)

Volviendo a nuestro ejemplo, esto es lo que hice.

$ git log commit 959781ec78c970d4797c5e938ec154de44d0151b (HEAD -> master) Author: Neil Kakkar Date: Mon Nov 5 07:32:55 2018 +0000 God why isn't this working last final BugFix commit affa90c0db78999d22c326fdbd6c1d5057228822 Author: Neil Kakkar Date: Mon Nov 5 07:32:19 2018 +0000 Final Final BugFix commit 2e9570cffc0a8206132d75c402d68351eda450bd Author: Neil Kakkar Date: Mon Nov 5 07:31:49 2018 +0000 Final BugFix commit 4560fc0ec6305d0b7bcfb4be1901438fd126d6d1 Author: Neil Kakkar Date: Mon Nov 5 07:31:21 2018 +0000 BugFix commit c747e6891af419119fd817dc69a2e122084aedae Merge: 3d01508 fb8b2fc Author: Neil Kakkar Date: Tue Oct 23 07:44:09 2018 +0100 resolve merge conflict

Now that the bug is fixed, I want to clean up my history before I push to master. This would work well too — when, say, I realise later on that I introduced another bug and need to revert to the previous version. In this case, c747e689 doesn’t have the best commit message to understand this.

$ git reset c747e6891af419119fd817dc69a2e122084aedae $ git log commit c747e6891af419119fd817dc69a2e122084aedae (HEAD -> master) Merge: 3d01508 fb8b2fc Author: Neil Kakkar Date: Tue Oct 23 07:44:09 2018 +0100 resolve merge conflict

There, all sorted?

$ git status On branch master Untracked files: (use "git add ..." to include in what will be committed) clean.txt nothing added to commit but untracked files present (use "git add" to track)

clean.txt is the file I had committed for the bug fix. Now, all I have to do is:

$ git add clean.txt $ git commit -m "fix bug: Unable to clean folder" [master d8487ca] fix bug: Unable to clean folder 1 file changed, 4 insertions(+) create mode 100644 clean.txt $ git log commit d8487ca8b9acfa9666bdf2c6b7fa27b3971bd957 (HEAD -> master) Author: Neil Kakkar Date: Mon Nov 5 07:41:41 2018 +0000 fix bug: Unable to clean folder commit c747e6891af419119fd817dc69a2e122084aedae Merge: 3d01508 fb8b2fc Author: Neil Kakkar Date: Tue Oct 23 07:44:09 2018 +0100 resolve merge conflict

There, done and dusted. Can you guess now, using the clues from the log, the reset command syntax and your tech-sense to figure out how it works behind the scenes?

Reset cuts off the commit-tree at the specified commit. All labels for that branch — if ahead — are moved back to the specified commit. Do the existing files stay in the object store though? You know how to check that now, Ace.

The files are also removed from the staging area. Now this might be a problem if you have lots of untracked/modified files which you don’t want to add.

How do you do that?

Can you pick up the clue I left in the beginning of this section?

Behaviour flags!

--soft keeps all files staged.

$ git reset --soft c747e6891af419119fd817dc69a2e122084aedae $ git status On branch master Changes to be committed: (use "git reset HEAD ..." to unstage) new file: clean.txt

--mixed is the default: Removes all files from staging area too.

--hard is hard-core. Deletes files from the object store — and directory as well. Use with extreme caution. There goes my bug fix*. Gone.

$ git reset --hard c747e6891af419119fd817dc69a2e122084aedae HEAD is now at c747e68 resolve merge conflict $ git status On branch master nothing to commit, working tree clean

*Well, not completely. Git is amazing. Have you heard of meta-meta data? A redundancy log of what happened in the repository? Yes, of course git keeps it!

$ git reflog c747e68 (HEAD -> master) [email protected]{0}: reset: moving to c747e6891af419119fd817dc69a2e122084aedae efc6d21 [email protected]{1}: commit: soft reset c747e68 (HEAD -> master) [email protected]{2}: reset: moving to c747e6891af419119fd817dc69a2e122084aedae d8487ca [email protected]{3}: commit: fix bug: Unable to clean folder c747e68 (HEAD -> master) [email protected]{4}: reset: moving to c747e6891af419119fd817dc69a2e122084aedae 959781e [email protected]{5}: commit: God why isn't this working last final BugFix affa90c [email protected]{6}: commit: Final Final BugFix 2e9570c [email protected]{7}: commit: Final BugFix 4560fc0 [email protected]{8}: commit: BugFix c747e68 (HEAD -> master) [email protected]{9}: commit (merge): resolve merge conflict 3d01508 [email protected]{10}: commit: add Master World b300387 (the-ending) [email protected]{11}: checkout: moving from the-middle to master fb8b2fc (the-middle) [email protected]{12}: commit: add Middle World b300387 (the-ending) [email protected]{13}: checkout: moving from master to the-middle b300387 (the-ending) [email protected]{14}: checkout: moving from the-middle to master b300387 (the-ending) [email protected]{15}: checkout: moving from master to the-middle b300387 (the-ending) [email protected]{16}: merge the-ending: Fast-forward a39b9fd [email protected]{17}: checkout: moving from the-ending to master b300387 (the-ending) [email protected]{18}: checkout: moving from master to the-ending a39b9fd [email protected]{19}: checkout: moving from the-ending to master b300387 (the-ending) [email protected]{20}: commit: add byeworld a39b9fd [email protected]{21}: checkout: moving from master to the-ending a39b9fd [email protected]{22}: commit (initial): Add helloworld

This is everything from the beginning of the example in the previous article. Does this mean I can recover things if I made an awful mistake?

$ git checkout d8487ca Note: checking out 'd8487ca'. You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by performing another checkout. If you want to create a new branch to retain commits you create, you may do so (now or later) by using -b with the checkout command again. Example: git checkout -b  HEAD is now at d8487ca... fix bug: Unable to clean folder $ ls byeworld clean.txt helloworld

There you have it.

Congratulations, you’re a Git Ninja — Apprentice now.

Is there something more you’d like to know about? Something that confused you about Git? Let me know below! I’ll try explaining it the way I learnt it!

Enjoyed this? Don’t miss a post again — subscribe to my mailing list!