├── .github └── workflows │ └── build.yaml ├── .gitignore ├── .vscode └── settings.json ├── LICENSE ├── README.md ├── docs ├── commands.md ├── cvs.md ├── git.md ├── gitflow.md ├── github-avanzado.md ├── github-flow.md ├── github-zenodo.md ├── github.md ├── images │ ├── distribuido-git.png │ ├── distribuido-tradicional.png │ ├── flujo-centralizado.png │ ├── flujo-dictador.png │ ├── flujo-integracion.png │ ├── git-central.png │ ├── git-distrib.png │ ├── git-estados.png │ ├── git-local.png │ ├── github-changes.png │ ├── github-code.png │ ├── github-edit.png │ ├── github-flow-merge.png │ ├── github-flow-merged.png │ ├── github-flow-pr-created.png │ ├── github-flow-pr.png │ ├── github-issues-list.png │ ├── github-issues-new.png │ ├── github-main.png │ ├── github-mergerequest.png │ ├── github-newrepo.png │ ├── github-proyect.png │ ├── github-pullconversation.png │ ├── github-pullrequest.png │ ├── github-pushed.png │ ├── github-quicksetup.png │ ├── github-sshkeys.png │ ├── github-topbar.png │ ├── gitlab-dashboard.png │ ├── gitlab-merge-ff.png │ ├── gitlab-mergerequest.png │ ├── gitlab-organizacion.png │ ├── gitlab-proyecto.png │ ├── logo-cuadrado-invertido.svg │ ├── logoasl-white.png │ └── logoasl.png ├── index.md ├── introduccion.md ├── ramas.md ├── referencias.md ├── stylesheets │ └── extra.css ├── usoavanzado.md └── usobasico.md ├── mkdocs.yml ├── poetry.lock └── pyproject.toml /.github/workflows/build.yaml: -------------------------------------------------------------------------------- 1 | name: Build documentation 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | 7 | jobs: 8 | # Build and deploy documentation site 9 | deploy: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout source form GitHub 13 | uses: actions/checkout@v4 14 | - name: Install poetry 15 | run: pipx install poetry 16 | - uses: actions/setup-python@v5 17 | with: 18 | python-version: '3.10' 19 | cache: 'poetry' 20 | - name: Install dependencies 21 | run: | 22 | poetry install 23 | - name: Deploy 24 | run: | 25 | poetry run mkdocs gh-deploy --force 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .cache 2 | poetry.toml 3 | site/ 4 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "yaml.schemas": { 3 | "https://squidfunk.github.io/mkdocs-material/schema.json": "mkdocs.yml" 4 | }, 5 | "yaml.customTags": [ 6 | "!ENV scalar", 7 | "!ENV sequence", 8 | "tag:yaml.org,2002:awesome-pages", 9 | "tag:yaml.org,2002:python/name:material.extensions.emoji.to_svg", 10 | "tag:yaml.org,2002:python/name:material.extensions.emoji.twemoji", 11 | "tag:yaml.org,2002:python/name:pymdownx.superfences.fence_code_format" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | ## creative commons 2 | 3 | # Attribution-NonCommercial-ShareAlike 4.0 International 4 | 5 | Creative Commons Corporation (“Creative Commons”) is not a law firm and does not provide legal services or legal advice. Distribution of Creative Commons public licenses does not create a lawyer-client or other relationship. Creative Commons makes its licenses and related information available on an “as-is” basis. Creative Commons gives no warranties regarding its licenses, any material licensed under their terms and conditions, or any related information. Creative Commons disclaims all liability for damages resulting from their use to the fullest extent possible. 6 | 7 | ### Using Creative Commons Public Licenses 8 | 9 | Creative Commons public licenses provide a standard set of terms and conditions that creators and other rights holders may use to share original works of authorship and other material subject to copyright and certain other rights specified in the public license below. The following considerations are for informational purposes only, are not exhaustive, and do not form part of our licenses. 10 | 11 | * __Considerations for licensors:__ Our public licenses are intended for use by those authorized to give the public permission to use material in ways otherwise restricted by copyright and certain other rights. Our licenses are irrevocable. Licensors should read and understand the terms and conditions of the license they choose before applying it. Licensors should also secure all rights necessary before applying our licenses so that the public can reuse the material as expected. Licensors should clearly mark any material not subject to the license. This includes other CC-licensed material, or material used under an exception or limitation to copyright. [More considerations for licensors](http://wiki.creativecommons.org/Considerations_for_licensors_and_licensees#Considerations_for_licensors). 12 | 13 | * __Considerations for the public:__ By using one of our public licenses, a licensor grants the public permission to use the licensed material under specified terms and conditions. If the licensor’s permission is not necessary for any reason–for example, because of any applicable exception or limitation to copyright–then that use is not regulated by the license. Our licenses grant only permissions under copyright and certain other rights that a licensor has authority to grant. Use of the licensed material may still be restricted for other reasons, including because others have copyright or other rights in the material. A licensor may make special requests, such as asking that all changes be marked or described. Although not required by our licenses, you are encouraged to respect those requests where reasonable. [More considerations for the public](http://wiki.creativecommons.org/Considerations_for_licensors_and_licensees#Considerations_for_licensees). 14 | 15 | ## Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Public License 16 | 17 | By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions. 18 | 19 | ### Section 1 – Definitions. 20 | 21 | a. __Adapted Material__ means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image. 22 | 23 | b. __Adapter's License__ means the license You apply to Your Copyright and Similar Rights in Your contributions to Adapted Material in accordance with the terms and conditions of this Public License. 24 | 25 | c. __BY-NC-SA Compatible License__ means a license listed at [creativecommons.org/compatiblelicenses](http://creativecommons.org/compatiblelicenses), approved by Creative Commons as essentially the equivalent of this Public License. 26 | 27 | d. __Copyright and Similar Rights__ means copyright and/or similar rights closely related to copyright including, without limitation, performance, broadcast, sound recording, and Sui Generis Database Rights, without regard to how the rights are labeled or categorized. For purposes of this Public License, the rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights. 28 | 29 | e. __Effective Technological Measures__ means those measures that, in the absence of proper authority, may not be circumvented under laws fulfilling obligations under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international agreements. 30 | 31 | f. __Exceptions and Limitations__ means fair use, fair dealing, and/or any other exception or limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material. 32 | 33 | g. __License Elements__ means the license attributes listed in the name of a Creative Commons Public License. The License Elements of this Public License are Attribution, NonCommercial, and ShareAlike. 34 | 35 | h. __Licensed Material__ means the artistic or literary work, database, or other material to which the Licensor applied this Public License. 36 | 37 | i. __Licensed Rights__ means the rights granted to You subject to the terms and conditions of this Public License, which are limited to all Copyright and Similar Rights that apply to Your use of the Licensed Material and that the Licensor has authority to license. 38 | 39 | j. __Licensor__ means the individual(s) or entity(ies) granting rights under this Public License. 40 | 41 | k. __NonCommercial__ means not primarily intended for or directed towards commercial advantage or monetary compensation. For purposes of this Public License, the exchange of the Licensed Material for other material subject to Copyright and Similar Rights by digital file-sharing or similar means is NonCommercial provided there is no payment of monetary compensation in connection with the exchange. 42 | 43 | l. __Share__ means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material available to the public including in ways that members of the public may access the material from a place and at a time individually chosen by them. 44 | 45 | m. __Sui Generis Database Rights__ means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world. 46 | 47 | n. __You__ means the individual or entity exercising the Licensed Rights under this Public License. Your has a corresponding meaning. 48 | 49 | ### Section 2 – Scope. 50 | 51 | a. ___License grant.___ 52 | 53 | 1. Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to: 54 | 55 | A. reproduce and Share the Licensed Material, in whole or in part, for NonCommercial purposes only; and 56 | 57 | B. produce, reproduce, and Share Adapted Material for NonCommercial purposes only. 58 | 59 | 2. __Exceptions and Limitations.__ For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions. 60 | 61 | 3. __Term.__ The term of this Public License is specified in Section 6(a). 62 | 63 | 4. __Media and formats; technical modifications allowed.__ The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a)(4) never produces Adapted Material. 64 | 65 | 5. __Downstream recipients.__ 66 | 67 | A. __Offer from the Licensor – Licensed Material.__ Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License. 68 | 69 | B. __Additional offer from the Licensor – Adapted Material.__ Every recipient of Adapted Material from You automatically receives an offer from the Licensor to exercise the Licensed Rights in the Adapted Material under the conditions of the Adapter’s License You apply. 70 | 71 | C. __No downstream restrictions.__ You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material. 72 | 73 | 6. __No endorsement.__ Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i). 74 | 75 | b. ___Other rights.___ 76 | 77 | 1. Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise. 78 | 79 | 2. Patent and trademark rights are not licensed under this Public License. 80 | 81 | 3. To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties, including when the Licensed Material is used other than for NonCommercial purposes. 82 | 83 | ### Section 3 – License Conditions. 84 | 85 | Your exercise of the Licensed Rights is expressly made subject to the following conditions. 86 | 87 | a. ___Attribution.___ 88 | 89 | 1. If You Share the Licensed Material (including in modified form), You must: 90 | 91 | A. retain the following if it is supplied by the Licensor with the Licensed Material: 92 | 93 | i. identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated); 94 | 95 | ii. a copyright notice; 96 | 97 | iii. a notice that refers to this Public License; 98 | 99 | iv. a notice that refers to the disclaimer of warranties; 100 | 101 | v. a URI or hyperlink to the Licensed Material to the extent reasonably practicable; 102 | 103 | B. indicate if You modified the Licensed Material and retain an indication of any previous modifications; and 104 | 105 | C. indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License. 106 | 107 | 2. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information. 108 | 109 | 3. If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable. 110 | 111 | b. ___ShareAlike.___ 112 | 113 | In addition to the conditions in Section 3(a), if You Share Adapted Material You produce, the following conditions also apply. 114 | 115 | 1. The Adapter’s License You apply must be a Creative Commons license with the same License Elements, this version or later, or a BY-NC-SA Compatible License. 116 | 117 | 2. You must include the text of, or the URI or hyperlink to, the Adapter's License You apply. You may satisfy this condition in any reasonable manner based on the medium, means, and context in which You Share Adapted Material. 118 | 119 | 3. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, Adapted Material that restrict exercise of the rights granted under the Adapter's License You apply. 120 | 121 | ### Section 4 – Sui Generis Database Rights. 122 | 123 | Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material: 124 | 125 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database for NonCommercial purposes only; 126 | 127 | b. if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Adapted Material, including for purposes of Section 3(b); and 128 | 129 | c. You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database. 130 | 131 | For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights. 132 | 133 | ### Section 5 – Disclaimer of Warranties and Limitation of Liability. 134 | 135 | a. __Unless otherwise separately undertaken by the Licensor, to the extent possible, the Licensor offers the Licensed Material as-is and as-available, and makes no representations or warranties of any kind concerning the Licensed Material, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable. Where disclaimers of warranties are not allowed in full or in part, this disclaimer may not apply to You.__ 136 | 137 | b. __To the extent possible, in no event will the Licensor be liable to You on any legal theory (including, without limitation, negligence) or otherwise for any direct, special, indirect, incidental, consequential, punitive, exemplary, or other losses, costs, expenses, or damages arising out of this Public License or use of the Licensed Material, even if the Licensor has been advised of the possibility of such losses, costs, expenses, or damages. Where a limitation of liability is not allowed in full or in part, this limitation may not apply to You.__ 138 | 139 | c. The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability. 140 | 141 | ### Section 6 – Term and Termination. 142 | 143 | a. This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically. 144 | 145 | b. Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates: 146 | 147 | 1. automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or 148 | 149 | 2. upon express reinstatement by the Licensor. 150 | 151 | For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License. 152 | 153 | c. For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License. 154 | 155 | d. Sections 1, 5, 6, 7, and 8 survive termination of this Public License. 156 | 157 | ### Section 7 – Other Terms and Conditions. 158 | 159 | a. The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed. 160 | 161 | b. Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License. 162 | 163 | ### Section 8 – Interpretation. 164 | 165 | a. For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License. 166 | 167 | b. To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions. 168 | 169 | c. No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor. 170 | 171 | d. Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority. 172 | 173 | > Creative Commons is not a party to its public licenses. Notwithstanding, Creative Commons may elect to apply one of its public licenses to material it publishes and in those instances will be considered the “Licensor.” Except for the limited purpose of indicating that material is shared under a Creative Commons public license or as otherwise permitted by the Creative Commons policies published at [creativecommons.org/policies](http://creativecommons.org/policies), Creative Commons does not authorize the use of the trademark “Creative Commons” or any other trademark or logo of Creative Commons without its prior written consent including, without limitation, in connection with any unauthorized modifications to any of its public licenses or any other arrangements, understandings, or agreements concerning use of licensed material. For the avoidance of doubt, this paragraph does not form part of the public licenses. 174 | > 175 | > Creative Commons may be contacted at creativecommons.org 176 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Taller de introducción a Git 2 | 3 |
4 | Aula Software Libre de la UCO 5 |
6 | 7 |
8 | 9 | ![built by developers](https://img.shields.io/badge/built%20by-developers%20%3C%2F%3E-orange.svg?longCache=true&style=for-the-badge) ![made with mkdocs](https://img.shields.io/badge/made%20with-mkdocs-green.svg?longCache=true&style=for-the-badge) ![uses git](https://img.shields.io/badge/uses-git-blue.svg?longCache=true&style=for-the-badge) 10 | 11 |
12 | 13 | Este taller forma parte de las actividades del [Aula de Software Libre de la 14 | Universidad de Córdoba](https://www.uco.es/aulasoftwarelibre). 15 | 16 | El contenido del mismo es en parte de producción propia, en parte de otros 17 | manuales libres que pueden encontrarse en la sección de [Referencias](docs/referencias.md). 18 | 19 | Contenido: 20 | 21 | - Inicio 22 | - Sistemas de control de versiones 23 | - Introducción a Git 24 | - Aspectos básicos de Git 25 | - Uso básico 26 | - Uso avanzado 27 | - Ramas 28 | - Administración de repositorios 29 | - Flujo de trabajo con Git (git flow) 30 | - Github 31 | - Referencias 32 | 33 | ## Agradecimientos 34 | 35 | Este curso ha sido impartido por las siguientes personas: 36 | 37 | - [Adrián López](https://github.com/AdrianLopezGue) 38 | - [Héctor Romero](https://github.com/cyberh99) 39 | - [Javier de Santiago](https://github.com/jdes01) 40 | - [José Márquez](https://github.com/IronSenior) 41 | - [Sergio Gómez](https://github.com/sgomez) 42 | - [Alba Palomino](https://github.com/Albapj01) 43 | 44 | ## Licencia 45 | 46 | El material está publicado con licencia [Atribución-NoComercial 4.0 Internacional (CC BY-NC 4.0)](https://creativecommons.org/licenses/by-nc/4.0/deed.es) 47 | -------------------------------------------------------------------------------- /docs/commands.md: -------------------------------------------------------------------------------- 1 | # Comandos de git 2 | 3 | Esta sección describe algunos de los comandos más interesantes de git 4 | 5 | ## Git stash (reserva) 6 | 7 | La orden `git stash` nos permite salvar momentáneamente el espacio de trabajo cuando tenemos que cambiar de rama o preparar la rama actual para sincronizar cambios. 8 | 9 | Las operaciones más importantes que podemos hacer con `git stash` son: 10 | 11 | ### git stash save 12 | 13 | Es equivalente a poner solo `git stash` pero nos permite realizar más acciones como: 14 | 15 | git stash save "Tu mensaje" 16 | git stash save -u 17 | 18 | El parámetro `-u` permite que se almacen también los ficheros sin seguimiento previo (_untracked_ en inglés, aquellos ficheros que no se han metido nunca en el repositorio). 19 | 20 | ### git stash list 21 | 22 | Permite mostrar la pila del stash. 23 | 24 | $ git stash list 25 | stash@{0}: On main: Stash con mensaje 26 | stash@{1}: WIP on main: 4ab21df First commit 27 | 28 | ### git stash apply 29 | 30 | Esta orden coge el stash que está arriba en la pila y lo aplica al espacio de trabajo actual. En este caso siempre es `stash@{0}`. El stash permanece en la pila. 31 | 32 | Se puede indicar como parámetro un stash en concreto. 33 | 34 | ### git stash pop 35 | 36 | Funciona igual que `git apply` con la diferencia de que el stash sí se borra de la pila. 37 | 38 | ### git stash show 39 | 40 | Muestra un resumen de los ficheros que se han modificado en ese stash. 41 | 42 | $ git stash show 43 | A.txt | 1 + 44 | B.txt | 3 +++ 45 | 2 file changed, 4 insertions(+) 46 | 47 | Para ver los cambios podemos usar el parámetro `-p` 48 | 49 | $ git stash show -p 50 | --- a/A.txt 51 | +++ b/A.txt 52 | @@ -45,6 +45,7 @@ nav: 53 | + This is a change 54 | 55 | Por defecto siempre muestra la cabeza de la pila. Igual que en casos anteriores podemos indicar un stash en concreto. 56 | 57 | $ git stash show stash@{1} 58 | 59 | ### git stash branch 60 | 61 | Permite crear una nueva rama a partir del último stash. Además, el mismo es borrado de la pila. Se puede especificar uno en concreto si lo queremos, como en el resto de comandos. 62 | 63 | git stash branch nombre-de-nueva-rama stash@{1} 64 | 65 | ### git stash clear 66 | 67 | Este comando borrar todos los stash de la pila. Es destructiva y no se puede deshacer. 68 | 69 | ### git stash drop 70 | 71 | Permite borrar un stash en concreto (o el último si no se indica ninguno). Como con clear, borrarlo implica que no se puede recuperar. 72 | 73 | ## Git worktree 74 | 75 | Uno de los problemas más habituales es tener que tocar una rama distinta a la que tenemos actualmente. Eso implica que si estamos en medio de un trabajo tendríamos que hacer un commit o un stash, lo cual a veces es bastante molesto. 76 | 77 | Con `git worktree` podemos crear un directorio de trabajo que contenga otra rama distinta, de forma temporal. No supone otro clon del repositorio porque ambos usan el mismo. 78 | 79 | ### git worktree add 80 | 81 | Esta función es la que crea el espacio de trabajo temporal. Imaginemos que estamos en una rama llamada `develop`: 82 | 83 | $ git worktree add ../project-main main 84 | $ git worktree add -b fix ../project-fix main 85 | 86 | La primera orden crea un directorio llamado project-main que contiene el estado de main. La segunda, que contiene el parámetro `-b` equivale a crear una nueva rama llamada fix, que se crea desde main (suponemos que no existe fix). 87 | 88 | ### git worktree list 89 | 90 | Muestra el listado de directorios y espacios de trabajo. 91 | 92 | $git worktree list 93 | /home/sergio/taller-de-git 3b63b4b [main] 94 | /home/sergio/fix 3b63b4b [fix] 95 | 96 | ### git worktree remove 97 | 98 | Borrar un espacio de trabajo. Hay que indicar el nombre entre corchetes que aparece en el listado 99 | 100 | $ git worktree delete fix 101 | 102 | ### git worktree prune 103 | 104 | Una cuestión importante, es que las ramas que estén desplegadas en otro espacio de trabajo, se encuentran bloqueadas y no se pueden desbloquear en otro distinto. 105 | 106 | Esto significa que si estamos trabajando en la rama developer, creamos otro worktree en otro directorio de la rama main, no podemos hacer pasar a main. No es posible tener la misma rama en varios espacios de trabajo. 107 | 108 | Si se ha borrado el directorio a mano (en vez de usando remove), eso no implica que el bloqueo desparezca. Con esta orden podemos hacer que git compruebe que los espacios de trabajo secundario se comprueben de nuevo para ver si siguen existiendo y se elimine el bloqueo. 109 | 110 | ## Git blame 111 | 112 | Lo ideal en un equipo de desarrollo es que el código pase por todas las manos para así mejorar su calidad. 113 | 114 | Con git blame podemos saber quién fue el último en modificar una línea concreta de código, en qué commit y en qué fecha lo hizo. 115 | 116 | $ git blame ejemplo.php 117 | 33cdd02c (Sergio Gómez 2020-01-20 16:58:52 +0100 8) name: "material" 118 | 33cdd02c (Sergio Gómez 2020-01-20 16:58:52 +0100 9) language: "es" 119 | -------------------------------------------------------------------------------- /docs/cvs.md: -------------------------------------------------------------------------------- 1 | # Sistemas de control de versiones 2 | 3 | ## Definición, clasificación y funcionamiento 4 | 5 | Se llama control de versiones a la gestión de los diversos cambios que se realizan sobre los elementos de algún producto o una configuración del mismo. Una versión, revisión o edición de un producto, es el estado en el que se encuentra dicho producto en un momento dado de su desarrollo o modificación. Aunque un sistema de control de versiones puede realizarse de forma manual, es muy aconsejable disponer de herramientas que faciliten esta gestión dando lugar a los llamados sistemas de control de versiones o SVC (del inglés System Version Control). 6 | 7 | Estos sistemas facilitan la administración de las distintas versiones de cada producto desarrollado, así como las posibles especializaciones realizadas (por ejemplo, para algún cliente específico). Ejemplos de este tipo de herramientas son entre otros: CVS, Subversion, SourceSafe, ClearCase, Darcs, Bazaar , Plastic SCM, Git, Mercurial, Perforce. 8 | 9 | ## Terminología 10 | 11 | Repositorio ("repository") 12 | : El repositorio es el lugar en el que se almacenan los datos actualizados e históricos de cambios. 13 | 14 | Revisión ("revision") 15 | : Una revisión es una versión determinada de la información que se gestiona. Hay sistemas que identifican las revisiones con un contador (Ej. subversion). Hay otros sistemas que identifican las revisiones mediante un código de detección de modificaciones (Ej. git usa SHA1). 16 | 17 | Etiqueta ("tag") 18 | : Los tags permiten identificar de forma fácil revisiones importantes en el proyecto. Por ejemplo se suelen usar tags para identificar el contenido de las versiones publicadas del proyecto. 19 | 20 | Rama ("branch") 21 | : Un conjunto de archivos puede ser ramificado o bifurcado en un punto en el tiempo de manera que, a partir de ese momento, dos copias de esos archivos se pueden desarrollar a velocidades diferentes o en formas diferentes de forma independiente el uno del otro. 22 | 23 | Cambio ("change") 24 | : Un cambio (o diff, o delta) representa una modificación específica de un documento bajo el control de versiones. La granularidad de la modificación que es considerada como un cambio varía entre los sistemas de control de versiones. 25 | 26 | Desplegar ("checkout") 27 | : Es crear una copia de trabajo local desde el repositorio. Un usuario puede especificar una revisión en concreto u obtener la última. El término 'checkout' también se puede utilizar como un sustantivo para describir la copia de trabajo. 28 | 29 | Confirmar ("commit") 30 | : Confirmar es escribir o mezclar los cambios realizados en la copia de trabajo del repositorio. Los términos 'commit' y 'checkin' también se pueden utilizar como sustantivos para describir la nueva revisión que se crea como resultado de confirmar. 31 | 32 | Conflicto ("conflict") 33 | : Un conflicto se produce cuando diferentes partes realizan cambios en el mismo documento, y el sistema es incapaz de conciliar los cambios. Un usuario debe resolver el conflicto mediante la integración de los cambios, o mediante la selección de un cambio en favor del otro. 34 | 35 | Cabeza ("head") 36 | : También a veces se llama tip (punta) y se refiere a la última confirmación, ya sea en el tronco ('trunk') o en una rama ('branch'). El tronco y cada rama tienen su propia cabeza, aunque HEAD se utiliza a veces libremente para referirse al tronco. 37 | 38 | Tronco ("trunk") 39 | : La única línea de desarrollo que no es una rama (a veces también llamada línea base, línea principal o máster). 40 | 41 | Fusionar, integrar, mezclar ("merge") 42 | : Una fusión o integración es una operación en la que se aplican dos tipos de cambios en un archivo o conjunto de archivos. Algunos escenarios de ejemplo son los siguientes: 43 | 44 | - Un usuario, trabajando en un conjunto de archivos, actualiza o sincroniza su copia de trabajo con los cambios realizados y confirmados, por otros usuarios, en el repositorio. 45 | - Un usuario intenta confirmar archivos que han sido actualizado por otros usuarios desde el último despliegue ('checkout'), y el software de control de versiones integra automáticamente los archivos (por lo general, después de preguntarle al usuario si se debe proceder con la integración automática, y en algunos casos sólo se hace si la fusión puede ser clara y razonablemente resuelta). 46 | - Un conjunto de archivos se bifurca, un problema que existía antes de la ramificación se trabaja en una nueva rama, y la solución se combina luego en la otra rama. 47 | - Se crea una rama, el código de los archivos es independiente editado, y la rama actualizada se incorpora más tarde en un único tronco unificado. 48 | 49 | ## Clasificación 50 | 51 | Podemos clasificar los sistemas de control de versiones atendiendo a la arquitectura utilizada para el almacenamiento del código: locales, centralizados y distribuidos. 52 | 53 | ### Locales 54 | 55 | Los cambios son guardados localmente y no se comparten con nadie. Esta arquitectura es la antecesora de las dos siguientes. 56 | 57 | ![Sistema de control de versiones local](images/git-local.png) 58 | 59 | ### Centralizados 60 | 61 | Existe un repositorio centralizado de todo el código, del cual es responsable un único usuario (o conjunto de ellos). Se facilitan las tareas administrativas a cambio de reducir flexibilidad, pues todas las decisiones fuertes (como crear una nueva rama) necesitan la aprobación del responsable. Algunos ejemplos son CVS y Subversion. 62 | 63 | ![Sistema de control de versiones centralizado](images/git-central.png) 64 | 65 | ### Distribuidos 66 | 67 | Cada usuario tiene su propio repositorio. Los distintos repositorios pueden intercambiar y mezclar revisiones entre ellos. Es frecuente el uso de un repositorio, que está normalmente disponible, que sirve de punto de sincronización de los distintos repositorios locales. Ejemplos: Git y Mercurial. 68 | 69 | ![Sistema de control de versiones distribuido](images/git-distrib.png) 70 | 71 | #### Ventajas de sistemas distribuidos 72 | 73 | - No es necesario estar conectado para guardar cambios. 74 | - Posibilidad de continuar trabajando si el repositorio remoto no está accesible. 75 | - El repositorio central está más libre de ramas de pruebas. 76 | - Se necesitan menos recursos para el repositorio remoto. 77 | - Más flexibles al permitir gestionar cada repositorio personal como se quiera. 78 | -------------------------------------------------------------------------------- /docs/git.md: -------------------------------------------------------------------------------- 1 | # Aspectos básicos de Git 2 | 3 | ## Instalación 4 | 5 | ### Instalando en Linux 6 | 7 | Si quieres instalar Git en Linux a través de un instalador binario, en general puedes hacerlo a través de la herramienta básica de gestión de paquetes que trae tu distribución. Si estás en Fedora, puedes usar yum: 8 | 9 | $ yum install git-core 10 | 11 | O si estás en una distribución basada en Debian como Ubuntu, prueba con apt-get: 12 | 13 | $ apt-get install git 14 | 15 | ### Instalando en Windows 16 | 17 | Instalar Git en Windows es muy fácil. El proyecto msysGit tiene uno de los procesos de instalación más sencillos. Simplemente descarga el archivo exe del instalador desde la página de GitHub, y ejecútalo: 18 | 19 | [http://msysgit.github.com/](http://msysgit.github.com/) 20 | 21 | Una vez instalado, tendrás tanto la versión de línea de comandos (incluido un cliente SSH que nos será útil más adelante) como la interfaz gráfica de usuario estándar. Se recomienda no modificar las opciones que trae por defecto el instalador. 22 | 23 | ### Instalando en MacOS 24 | 25 | En MacOS se recomienda tener instalada la herramienta [homebrew](https://brew.sh/). Después, es tan fácil como ejecutar: 26 | 27 | $ brew install git 28 | 29 | ## Configuración 30 | 31 | ### Tu identidad 32 | 33 | Lo primero que deberías hacer cuando instalas Git es establecer tu nombre de usuario y dirección de correo electrónico. Esto es importante porque las confirmaciones de cambios (commits) en Git usan esta información, y es introducida de manera inmutable en los commits que envías: 34 | 35 | $ git config --global user.name "John Doe" 36 | $ git config --global user.email johndoe@example.com 37 | 38 | También se recomienda configurar el siguiente parámetro: 39 | 40 | $ git config --global push.default simple 41 | 42 | ### Bash Completion 43 | 44 | _Bash completion_ es una utilidad que permite a bash completar órdenes y parámetros. Por defecto suele venir desactivada en Ubuntu y es necesario modificar el archivo `$HOME/.bashrc` para poder activarla. Simplemente hay que descomentar las líneas que lo activan, 45 | -------------------------------------------------------------------------------- /docs/gitflow.md: -------------------------------------------------------------------------------- 1 | # Flujo de trabajo con Git (git flow) 2 | 3 | !!! warning 4 | 5 | Esta sección se mantiene por motivos históricos y de documentación. En general, ya se considera 6 | una mala práctica seguir este flujo de trabajo. Aunque hay muchos equipos que aun lo utilizan, 7 | por lo que viene bien conocerla, no deberías aplicarla en proyectos nuevos. 8 | 9 | ## La importancia de la organización del flujo de trabajo 10 | 11 | En la introducción vimos los diferentes esquemas de organización externa de los repositorios (es decir, en lo relativo a los usuarios que componen el equipo de trabajo). 12 | 13 | Pero el repositorio en sí también tiene su esquema de organización. 14 | 15 | En los ejemplos hemos visto que usabamos una rama máster y creábamos ramas para añadir funcionalidades que luego integrábamos. Es un forma de trabajar de las muchas que hay propuestas, posiblemente la más simple, pero tiene el inconveniente de dejar la rama máster a expensas de una mala actualización y quedarnos sin una rama estable. Por eso, hay otras propuestas mejores que permiten separar el trabajo de desarrollo con el mantenimiento de las versiones estables. Una de las más conocidas es la propuesta por [Vincent Driessen](http://nvie.com/posts/a-successful-git-branching-model/) y que podemos ver en la figura siguiente. 16 | 17 | ![Git flow](images/gitlab-organizacion.png) 18 | 19 | ### Las ramas principales 20 | 21 | En este esquema hay dos ramas principales con un tiempo de vida indefinido: 22 | 23 | - main (_origin/main_): el código apuntado por _HEAD_ siempre contiene un estado listo para producción. 24 | - develop (_origin/develop_): el código apuntado por _HEAD_ siempre contiene los últimos cambios desarrollados para la próxima versión del software. También se le puede llamar _rama de integración_. No es necesariamente estable. 25 | 26 | Cuando el código de la rama de desarrollo es lo suficientemente estable, se integra con la rama main y una nueva versión es lanzada. 27 | 28 | ### Las ramas auxiliares 29 | 30 | Para labores concretas, pueden usarse otro tipo de ramas, las cuales tienen un tiempo de vida definido. Es decir, cuando ya no son necesarias se eliminan: 31 | 32 | - Ramas de funcionalidad (feature branches) 33 | - Ramas de versión (release branches) 34 | - Ramas de parches (hotfix branches) 35 | 36 | #### Feature branches 37 | 38 | - Pueden partir de: develop 39 | - Deben fusionarse con: develop 40 | - Convenición de nombres: feature-NUMissue-\*. 41 | 42 | #### Release branches 43 | 44 | - Pueden partir de: develop 45 | - Deben fusionarse con: develop y main 46 | - Convenición de nombres: release-\* 47 | 48 | #### Hotfix branches 49 | 50 | - Pueden partir de: main 51 | - Deben fusionarse con: develop y main 52 | - Convenición de nombres: hotfix-\* 53 | 54 | ## La extensión flow de Git 55 | 56 | Una de las ventajas de Git es que, además, es extensible. Es decir, se pueden crear nuevas órdenes como si de plugins se tratara. Una de las más usadas es [gitflow](https://github.com/nvie/gitflow), que está basada en el artículo que hablamos al principio de este capítulo. 57 | 58 | ### Instalación 59 | 60 | Aunque la fuente original de la extensión es del mismo autor del artículo, el código no se encuentra ya muy actualizado y hay un fork bastante más activo en [petervanderdoes/gitflow](https://github.com/petervanderdoes/gitflow). En el wiki del repositorio están las [instrucciones de instalación](https://github.com/petervanderdoes/gitflow/wiki) para distintos sistemas. Una vez instalados tendremos una nueva órden: `git flow`. 61 | 62 | ### Uso 63 | 64 | Para cambiar a las ramas main y develop, seguiremos usando `git checkout`, pero para trabajar con las ramas antes indicadas gitflow nos facilita las siguientes órdenes: 65 | 66 | 67 | #### - git flow init: 68 | Inicializa el espacio de trabajo. De forma automática, crea las ramas que necesitamos y permite configurar el nombre de las mismas. 69 | 70 | ``` 71 | $ git flow init 72 | Initialized empty Git repository in ~/project/.git/ 73 | No branches exist yet. Base branches must be created now. 74 | Branch name for production releases: [main] 75 | Branch name for "next release" development: [develop] 76 | 77 | How to name your supporting branch prefixes? 78 | Feature branches? [feature/] 79 | Release branches? [release/] 80 | Hotfix branches? [hotfix/] 81 | Support branches? [support/] 82 | Version tag prefix? [] 83 | 84 | $ git branch 85 | * develop 86 | main 87 | ``` 88 | 89 | Podemos ver que por defecto (usando intro en vez de escribir nada) pone nombres por defecto a cada rama. Con `git branch` comprobamos que ramas existen y en cual nos encontramos. 90 | 91 | 92 | 93 | 94 | #### - git flow feature: 95 | Permite crear y trabajar con ramas de funcionalidades. 96 | 97 | ``` 98 | $ git flow feature start feature_branch 99 | 100 | ``` 101 | 102 | Así creamos una rama 'feature/feature_branch' y nos mueve automáticamente a ella. 103 | En esta haremos los cambios que queramos en nuestro repositorio. Cuando queramos acabar de usar la rama, haremos un commit y la finalizaremos: 104 | 105 | ``` 106 | $ git flow feature stop feature_branch 107 | 108 | ``` 109 | 110 | Esto finaliza nuestra rama y la integra automáticamente a la rama develop. Si queremos seguir cambiando nuestro repositorio abriremos una nueva rama feature. 111 | 112 | 113 | 114 | 115 | #### - git flow release: 116 | Permite crear y trabajar con ramas de versiones. 117 | Cuando entendemos que despues de todas las funcionalidades (features, cambios en nuestro repositorio) nuestro trabajo esta listo para ser publicado, abriremos una rama release, que nacera de nuestra rama develop. 118 | 119 | ``` 120 | $ git flow release start 0.1.0 121 | Switched to a new branch 'release/0.1.0' 122 | ``` 123 | 124 | Usaremos un tag para identificar de que release se trata. 125 | Ahora podemos hacer los cambios que estimemos oportuno para integrar todas las features que el repositorio ha sufrido hasta el momento. Tras hacer commit a todo el proceso, podemos cerrar la rama release. 126 | 127 | ``` 128 | $git flow release finish '0.1.0' 129 | ``` 130 | 131 | Esto la integrará de forma automática con main (con esto finalizamos el proceso de 'subir a producción' nuestro codigo) y con la rama develop, para que las futuras features estén al día. 132 | 133 | 134 | 135 | 136 | #### - git flow hotfix: 137 | Permite crear y trabajar con ramas de parches. Esto lo usaremos para hacer cambios rapidos que no puedan esperar a la proxima integracion de una release. 138 | 139 | ``` 140 | $ git flow hotfix start hotfix_branch 141 | ``` 142 | 143 | Tras hacer commit finalizamos la rama hotfix. Esta se fusionará con nuestra rama main y con nuestra rama develop para que esta también esté al día de los últimos cambios. 144 | 145 | ``` 146 | $ git flow hotfix finish hotfix_branch 147 | ``` 148 | -------------------------------------------------------------------------------- /docs/github-avanzado.md: -------------------------------------------------------------------------------- 1 | # Github avanzado 2 | 3 | Esta sección trata de cómo colaborar con proyectos de terceros. 4 | 5 | ## Clonar un repositorio 6 | 7 | Nos vamos a la web del proyecto en el que queremos colaborar. En este caso el proyecto se encuentra en [https://github.com/sgomez/miniblog](https://github.com/sgomez/miniblog). Pulsamos en el botón de fork y eso creará una copia en nuestro perfil. 8 | 9 | ![Barra de información de proyecto](images/github-proyect.png) 10 | 11 | Una vez se termine de clonar el repositorio, nos encontraremos con el espacio de trabajo del mismo: 12 | 13 | - En la parte superior información sobre los commits, ramas, etiquetas, etc. 14 | - Justo debajo un explorador de archivos. 15 | - En la parte derecha un selector para cambiar de contexto entre: explorador de código, peticiones de colaboración (pull request), wiki, configuración, etc. 16 | - Justo abajo a la derecha información sobre como clonar localmente o descargar un proyecto. 17 | 18 | ![Espacio de trabajo](images/github-main.png) 19 | 20 | Github nos permite clonar localmente un proyecto por tres vías: HTTPS, SSH y Subversion. Seleccionamos SSH y copiamos el texto que después añadiremos a la orden `git clone` como en la primera línea del siguiente grupo de órdenes: 21 | 22 | $ git clone git@github.com:miusuario/miniblog.git 23 | $ cd miniblog 24 | $ composer.phar install 25 | $ php console create-schema 26 | 27 | Lo que hace el código anterior es: 28 | 29 | 1. Clona el repositorio localmente 30 | 2. Entramos en la copia 31 | 3. Instalamos las dependencias que la aplicación tiene 32 | 4. Arrancamos un servidor web para pruebas 33 | 34 | Y probamos que nuestra aplicación funciona: 35 | 36 | $ php -S localhost:9999 -t web/ 37 | 38 | Podemos usar dos direcciones para probarla: 39 | 40 | - Frontend: `http://localhost:9999/index_dev.php` 41 | - Backend: `http://localhost:9999/index_dev.php/admin/` con usuario admin y contraseña 1234. 42 | 43 | ### Sincronizar con el repositorio original 44 | 45 | Cuando clonamos un repositorio de otro usuario hacemos una copia del original. Pero esa copia es igual al momento en el que hicimos la copia. Cuando el repositorio original cambie, que lo hará, nuestro repositorio no se actualizará solo. ¡Son dos repositorios diferentes! Necesitamos una manera de poder incorporar los cambios que vaya teniendo el repositorio original en el nuestro. Para eso crearemos una nueva rama remota. Por convenio, y como vimos anteriormente, ya existe una rama remota llamada _origin_ que apunta al repositorio de donde clonamos el proyecto, en este caso apunta a nuestro fork en github: 46 | 47 | $ git remote show origin 48 | * remote origin 49 | Fetch URL: git@github.com:miusuario/miniblog.git 50 | Push URL: git@github.com:miusuario/miniblog.git 51 | HEAD branch (remote HEAD is ambiguous, may be one of the following): 52 | develop 53 | main 54 | Remote branches: 55 | develop tracked 56 | main tracked 57 | Local branch configured for 'git pull': 58 | main merges with remote main 59 | Local ref configured for 'git push': 60 | main pushes to main (up to date) 61 | 62 | También por convenio, la rama remota que hace referencia al repositorio original se llama _upstream_ y se crea de la siguiente manera: 63 | 64 | $ git remote add upstream git@github.com:sgomez/miniblog.git 65 | $ git remote show upstream 66 | * remote upstream 67 | Fetch URL: git@github.com:sgomez/miniblog.git 68 | Push URL: git@github.com:sgomez/miniblog.git 69 | HEAD branch: main 70 | Remote branches: 71 | develop new (next fetch will store in remotes/upstream) 72 | main new (next fetch will store in remotes/upstream) 73 | Local ref configured for 'git push': 74 | main pushes to main (local out of date) 75 | 76 | En este caso, la URI debe ser siempre la del proyecto original. Y ahora para incorporar actualizaciones, usaremos el merge en dos pasos: 77 | 78 | $ git fetch upstream 79 | $ git merge upstream/main 80 | 81 | Recordemos que _fetch_ solo trae los cambios que existan en el repositorio remoto sin hacer ningún cambio en nuestro repositorio. Es la orden _merge_ la que se encarga de que todo esté sincronizado. En este caso decimos que queremos fusionar con la rama _main_ que está en el repositorio _upstream_. 82 | 83 | ### Creando nuevas funcionalidades 84 | 85 | Vamos a crear una nueva funcionalidad: vamos a añadir una licencia de uso. Para ello preferentemente crearemos una nueva rama. 86 | 87 | $ git checkout -b add-license 88 | $ echo "LICENCIA MIT" > LICESE 89 | # el error es intencionado 90 | $ git add LICESE 91 | $ git commit -m "Archivo de licencia de uso" 92 | 93 | En principio habría que probar que todo funciona bien y entonces integraremos en la rama _main_ de nuestro repositorio y enviamos los cambios a Github: 94 | 95 | $ git checkout main 96 | $ git merge add-license --no-ff 97 | $ git branch -d add-license 98 | # Borramos la rama que ya no nos sirve para nada 99 | $ git push --set-upstream origin add-license 100 | # Enviamos la rama a nuestro repositorio origin 101 | 102 | Si volvemos a Github, veremos que nos avisa de que hemos subido una nueva rama y si queremos crear un pull request. 103 | 104 | ![Aviso de nueva rama](images/github-pushed.png) 105 | 106 | Pulsamos y entramos en la petición de _Pull Request_. Este es el momento para revisar cualquier error antes de enviar al dueño del repositorio. Como vemos hemos cometido uno, nombrando el fichero, si lo correguimos debemos hacer otro push para ir actualizando la rama. Cuando esté lista volvemos aquí y continuamos. Hay que dejar una descripción del cambio que vamos a hacer. 107 | 108 | ![Creando un Pull Request](images/github-mergerequest.png) 109 | 110 | Una vez hemos terminado y nos aseguramos que todo está correcto, pulsamos _Send pull request_ y le llegará nuestra petición al dueño del proyecto. 111 | 112 | ![Gestión de un _Pull Request_](images/github-pullrequest.png) 113 | 114 | Sin embargo, para esta prueba, no vamos a cambiar el nombre del archivo y dejaremos el error como está. Así de esta manera al administrador del proyecto le llegará el _Pull Request_ y la lista de cambios. Ahora en principio, cabría esperar que el administrador aprobara los cambios, pero podría pasar que nos indicara que cambiemos algo. En ese caso solo habría que modificar la rama y volverla a enviar. 115 | 116 | $ git mv LICESE LICENSE 117 | $ git commit -m "Fix: Nombre de archivo LICENSE" 118 | $ git push 119 | 120 | Ahora sí, el administrador puede aprobar la fusión y borrar la rama del repositorio. El panel de Github permite aceptar los cambios directamente o informa de como hacer una copia de la rama ofrecida por el usuario para hacer cambios, como puede verse en la siguiente imagen. 121 | 122 | ![Conversación en un _Pull Request_](images/github-pullconversation.png) 123 | 124 | Una vez que se han aceptado los cambios, podemos borrar la rama y actualizar nuestro repositorio con los datos del remoto como hicimos antes. ¿Por qué actualizar desde el remoto y no desde nuetra rama _add-license_? Pues porque usualmente el administrador puede haber modificado los cambios que le hemos propuesto, o incluso una tercera persona. Recordemos el cariz colaborativo que tiene Github. 125 | 126 | $ git checkout main 127 | $ git branch -d add-license 128 | # Esto borra la rama local 129 | $ git push origin --delete add-license 130 | # Esto borra la rama remota. También puede hacerse desde la web. 131 | 132 | ### Todo esto es algo complicado... 133 | 134 | Sí, lo es, al menos al principio. Git tiene una parte muy sencilla que es el uso del repositorio local (órdenes tales como add, rm, mv y commit). El siguiente nivel de complejidad lo componen las órdenes para trabajar con ramas y fusionarlas (checkout, branch, merge, rebase) y por último, las que trabajan con repositorios remotos (pull, push, fetch, remote). Además hay otra serie de órdenes para tener información (diff, log, status) o hacer operaciones de mantenimiento (fsck, gc). Lo importante para no perderse en Git, es seguir la siguiente máxima: 135 | 136 | > No avanzar al siguiente nivel de complejidad, hasta no haber entendido completamente el anterior. 137 | 138 | Muy poco sentido tiene ponernos a crear ramas en github si aún no entendemos cómo se crean localmente y para que deben usarse. En la parte de referencias hay varios manuales en línea, incluso tutoriales interactivos. También hay mucha documentación disponible en Github que suele venir muy bien explicada. En caso de que tengamos un problema que no sepamos resolver, una web muy buena es [StackOverflow](http://stackoverflow.com/). Es una web de preguntas y respuestas para profesionales; es muy difícil que se os plantee una duda que no haya sido ya preguntada y respondida en esa web. Eso sí, el inglés es imprescindible. 139 | 140 | ## Último paso, documentación. 141 | 142 | Github permite crear documentación. En primer lugar, generando un archivo llamado `README.md`. También permite crear una web propia para el proyecto y, además, una wiki. Para marcar el texto, se utiliza un lenguaje de marcado de texto denominado _Markdown_. En la siguiente web hay un tutorial interactivo: [http://www.markdowntutorial.com/](http://www.markdowntutorial.com/). Como en principio, no es necesario saber Markdown para poder trabajar con Git o con Github, no vamos a incidir más en este asunto. 143 | 144 | En el propio GitHub podemos encontrar algunas plantillas que nos sirvan de referencia. 145 | 146 | Algunos ejemplos: 147 | 148 | - [Plantilla básica](https://gist.github.com/PurpleBooth/109311bb0361f32d87a2) 149 | - [Plantilla avanzada](https://github.com/othneildrew/Best-README-Template) 150 | 151 | ### Documentación del curso 152 | 153 | Esta documentación está hecha en Markdown y pasada a HTML gracia a la herramienta [mkdocs](https://www.mkdocs.org/). La plantilla usada es [Material for MkDocs](https://squidfunk.github.io/mkdocs-material/). 154 | 155 | El material está publicado con licencia [Atribución-NoComercial 4.0 Internacional (CC BY-NC 4.0)](https://creativecommons.org/licenses/by-nc/4.0/deed.es) 156 | -------------------------------------------------------------------------------- /docs/github-flow.md: -------------------------------------------------------------------------------- 1 | # Flujo de trabajo en GitHub 2 | 3 | ## Paso 0. Abrir una incidencia (issue) 4 | 5 | Habitualmente el trabajo puede partir a raíz de una reporte por parte de un miembro del equipo o de una persona externa. Para eso tenemos la sección _Issues_. 6 | 7 | ![Listado de Issues](images/github-issues-list.png) 8 | 9 | Una issue cuando se crea se compone de un título y una descripción en 10 | Markdown. Si la persona es miembro del equipo, opcionalmente puede 11 | asignarle una serie de metadatos: etiquetas (labels), hitos 12 | (milestone), proyecto al que pertenece o responsables encargados 13 | de cerrar la incidencia. 14 | 15 | ![Nueva Issue](images/github-issues-new.png) 16 | 17 | Una vez creado, al mismo se le asignará un número.ç 18 | 19 | !!! example 20 | 21 | Vamos a crear una incidencia llamada "Crear archivo de autores", donde indiquemos que vamos a crear un archivo `AUTHORS.md` con 22 | la lista de desarrolladores del proyecto. 23 | 24 | ## Paso 1. Crear una rama 25 | 26 | Crearemos una rama cada vez que queramos implementar una nueva característica al proyecto que estamos realizando. La misma puede estar provocada por una incidencia o no. 27 | 28 | !!! tip 29 | 30 | Es una buena costumbre crear en Issues el listado de casos de uso, 31 | requisitos, hostorias de usuario o tareas (como lo queramos llamar), 32 | para tener un registro del trabajo que llevamos y el que nos queda. 33 | 34 | El nombre de la rama puede ser el que creamos conveniente, pero hay que 35 | intentar ser coherente y usar siempre el mismo método, sobre todo si 36 | trabajamos en equipo. 37 | 38 | Un método puede ser el siguiente: 39 | 40 | $ # tipo-número/descripción 41 | $ git checkout -b feature-1/create-changelog 42 | $ git checkout -b hotfix-2/updated-database 43 | 44 | En entornos de trabajo multiusuario se puede usar el siguiente: 45 | 46 | $ # usuario/tipo-número/descripción 47 | $ git checkout -b sgomez/feature-1/create-changelog 48 | $ git checkout -b sgomez/hotfix-2/updated-database 49 | 50 | De esa manera, podemos seguir fácilmente quién abrió la rama, en qué consiste y a qué _issues_ está conectada. Pero como decimos es más un convenio que una imposición, pudiéndole poner el nombre que queramos. 51 | 52 | Vamos a crear la rama y los commits correspondientes y subir la rama con push al servidor. 53 | 54 | $ git checkout -b sgomez/feature-1/create-changelog 55 | $ git add AUTHORS.md 56 | $ git commit -m "Añadido fichero de autores" 57 | 58 | El archivo puede contener, por ejemplo, lo siguiente: 59 | 60 | # AUTHORS 61 | 62 | * Sergio Gómez 63 | 64 | Hacemos push y obtenemos algo como esto: 65 | 66 | $ git push 67 | fatal: The current branch sgomez/feature-1/create-changelog has no upstream branch. 68 | To push the current branch and set the remote as upstream, use 69 | 70 | git push --set-upstream origin sgomez/feature-1/create-changelog 71 | 72 | Como la rama es nueva, git no sabe _dónde_ debe hacer push. Le indicamos que debe hacerla en _origin_ y además que guarde la vinculación (equivalente al parámetro -u que vimos en el capítulo anterior). Probamos de nuevo: 73 | 74 | $ git push -u origin sgomez/feature-1/create-changelog 75 | Enumerating objects: 4, done. 76 | Counting objects: 100% (4/4), done. 77 | Delta compression using up to 4 threads 78 | Compressing objects: 100% (2/2), done. 79 | Writing objects: 100% (3/3), 1.03 KiB | 1.03 MiB/s, done. 80 | Total 3 (delta 0), reused 0 (delta 0) 81 | remote: 82 | remote: Create a pull request for 'sgomez/feature-1/create-changelog' on GitHub by visiting: 83 | remote: https://github.com/sgomez/taller-de-git/pull/new/sgomez/feature-1/create-changelog 84 | remote: 85 | To github.com:sgomez/taller-de-git.git 86 | * [new branch] sgomez/feature-1/create-changelog -> sgomez/feature-1/create-changelog 87 | Branch 'sgomez/feature-1/create-changelog' set up to track remote branch 'sgomez/feature-1/create-changelog' from 'origin'. 88 | 89 | Ahora la rama ya se ha subido y nos informa, además, de que podemos crear un _Pull Request_ (PR). Si vamos al enlace que nos aparece veremos lo siguiente: 90 | 91 | ![Nuevo Pull Request](images/github-flow-pr.png) 92 | 93 | Aquí podemos informar de en qué consiste la rama que estamos enviando. Si ya tenemos una _issue_ abierta, no es necesario repetir la misma información. Podemos hacer referencia con el siguiente texto: 94 | 95 | Closes #1 96 | 97 | Esto lo que le indica a GitHub que esta PR cierra el _issues_ número 1. Cuando se haga el merge de la rama, automáticamente se cerrará la incidencia. 98 | 99 | Lo hacemos y le damos a crear. 100 | 101 | ![Nuevo Pull Request](images/github-flow-pr-created.png) 102 | 103 | ## Paso 2. Crear commits 104 | 105 | A partir de ahora podemos seguir creando commits en local y enviarlos hasta que terminemos de trabajar. 106 | 107 | Editamos el archivo AUTHORS.md . 108 | 109 | # AUTHORS 110 | 111 | * Sergio Gómez 112 | * John Doe 113 | 114 | Y mandamos otro commit 115 | 116 | $ git commit -am "Actualizado AUTHORS.md" 117 | $ git push 118 | 119 | Si volvemos a la página de PR, veremos que aparece el nuevo commit que acabamos de enviar. 120 | 121 | ## Paso 3. Discutir 122 | 123 | GitHub permite que entre los desarrolladores se pueda abrir una discusión sobre el código, de tal manera que el trabajo de crear la rama sea colaborativo. Se puede incluso pedir revisiones por parte de terceros y que esas revisiones sean obligatorias antes de aceptar los cambios. 124 | 125 | ## Paso 4. Desplegar 126 | 127 | Una vez que hemos terminado de crear la función de la rama ya podemos incorporar los cambios a _main_. Este trabajo ya no es necesario hacerlo en local y GitHub nos proporciona 3 maneras de hacerlo: 128 | 129 | ![Cómo cerrar un Pull Request](images/github-flow-merge.png) 130 | 131 | ### Crear un merge commit 132 | 133 | Esta opción es el equivalente a hacer lo siguiente en nuestro repositorio: 134 | 135 | $ git checkout main 136 | $ git merge --no-ff sgomez/feature-1/create-changelog 137 | $ git push 138 | 139 | Es decir, el equivalente a hacer un merge entre nuestra rama y main. 140 | 141 | !!! info 142 | GitHub siempre desactiva el _fast forward_. 143 | 144 | ### Crear un rebase y merge 145 | 146 | Esta opción es el equivalente a hacer lo siguiente en nuestro repositorio 147 | 148 | $ git rebase main 149 | $ git checkout main 150 | $ git merge --no-ff sgomez/feature-1/create-changelog 151 | $ git push 152 | 153 | Es decir, nos aseguramos de que nuestra rama está al final de _main_ haciendo _rebase_, como vimos en el capítulo de ramas, y posteriormente se hace el merge. 154 | 155 | ### Crear un squash commit y un merge 156 | 157 | Esta opción es el equivalente a hacer lo siguiente en nuestro repositorio: 158 | 159 | $ git checkout main 160 | $ git merge --squash sgomez/feature-1/create-changelog 161 | $ git push 162 | 163 | Esta opción es algo especial. En vez de aplicar cada uno de los commits en la rama main, ya sea directamente (_fast forward_) o no, lo que hace es crear un solo commit con los cambios de todos los commits de la rama. El efecto final es como si en la rama solo hubiera producido un solo commit. 164 | 165 | Vamos a seleccionar este último (squash and merge) y le damos al botón para activarlo. Nos saldrá una caja para que podamos crear una descripción del commit y le damos a confirmar. 166 | 167 | ![Pull Request cerrado](images/github-flow-merge.png) 168 | 169 | Ya hemos terminado y nos aparecerá una opción para borrar la rama, lo más recomendado para no tener ramas obsoletas. 170 | 171 | Las consecuencias de esta acción son las siguientes: 172 | 173 | 1. El PR aparecerá como estado _merged_ y en la lista de PR como cerrado. 174 | 1. El _issue_ que abrimos se habrá cerrado automáticamente. 175 | 1. En el listado de commits aparecerá solo uno con un enlace al PR (en vez de los dos commits que hicimos). 176 | 177 | ## Paso 5. Sincronizar 178 | 179 | Hemos cambiado el repositorio en GitHub, pero nuestra rama main no contiene los mismos cambios que el de origin. Así que nos toca sincronizar y borrar la rama obsoleta: 180 | 181 | $ git checkout main 182 | $ git pull --rebase --autostash 183 | $ git branch -D sgomez/feature-1/create-changelog 184 | 185 | !!! info 186 | 187 | ¿Por qué _squash and merge_ y no un _merge_ o _rebase_? De nuevo 188 | depende de los gustos de cada equipo de desarrollo. Las cracterísticas de _squash_ es que elimina (relativamente) rastros de errores intermedios mientras se implementaba la rama, deja menos commits en la rama _main_ y nos enlace al PR donde se implementaron los cambios. 189 | 190 | Para algunas personas estas características son unas ventajas, para otras no. Lo mejor es experimentar cada opción y cada uno decida 191 | como quiere trabajar. 192 | -------------------------------------------------------------------------------- /docs/github-zenodo.md: -------------------------------------------------------------------------------- 1 | # Citar proyectos en GitHub 2 | 3 | Extraído de la [guía oficial de GitHub](https://guides.github.com/activities/citable-code/). 4 | 5 | A través de una aplicación de terceros (Zenodo, financiado por el CERN), es posible crear un DOI para uno de nuestros proyectos. 6 | 7 | Estos son los pasos 8 | 9 | ## Paso 1. Elegir un repositorio 10 | 11 | Este repositorio debe ser abierto (público), o de lo contrario Zenodo no podrá acceder al mismo. Hay que recordar escoger una licencia para el proyecto. Esta web puede ayudarnos [http://choosealicense.com/](http://choosealicense.com/). 12 | 13 | ## Paso 2. Entrar en Zenodo 14 | 15 | Iremos a [Zenodo](http://zenodo.org/) y haremos login con GitHub. Lo único que tenemos que hacer en esta parte es autorizar a Zenodo a conectar con nuestra cuenta de GitHub. 16 | 17 | !!! important 18 | 19 | Si deseas archivar un repositorio que pertenece a una organización en GitHub, deberás asegurarte de que el administrador de la organización haya habilitado el acceso de terceros a la aplicación Zenodo. 20 | 21 | ## Paso 3. Seleccionar los repositorios 22 | 23 | En este punto, hemos autorizado a Zenodo para configurar los permisos necesarios para permitir el archivado y la emisión del DOI. Para habilitar esta funcionalidad, simplemente haremo clic en el botón que está junto a cada uno de los repositorios que queremos archivar. 24 | 25 | !!! important 26 | 27 | Zenodo solo puede acceder a los repositorios públicos, así que debemos asegurarnos de que el repositorio que deseamos archivar sea público. 28 | 29 | ## Paso 4. Crear una nueva _release_ 30 | 31 | Por defecto, Zenodo realiza un archivo de nuestro repositorio de GitHub cada vez que crea una nueva versión. Como aún no tenemos ninguna, tenemos que volver a la vista del repositorio principal y hacer clic en el elemento del encabezado de versiones (_releases_). 32 | 33 | ## Paso 5. Acuñar un DOI 34 | 35 | Antes de que Zenodo pueda emitir un DOI para nuestro repositorio, deberemos proporcionar cierta información sobre el repositorio de GitHub que acaba de archivar. 36 | 37 | Una vez que estemos satisfechos con la descripción, heremos clic en el botón publicar. 38 | 39 | ## Paso 6. Publicar 40 | 41 | De vuelta a nuestra página de Zenodo, ahora deberíamos ver el repositorio listado con una nueva insignia que muestra nuestro nuevo DOI. 42 | 43 | !!! tip 44 | 45 | Podemos colocar la insigna en nuestro proyecto. Para eso haremos clic en la imagen DOI gris y azul. Se abrirá una ventana emergente y el texto que aparece como _Markdown_ es el que deberemos copiar 46 | en nuestro archivo _README.md_. 47 | -------------------------------------------------------------------------------- /docs/github.md: -------------------------------------------------------------------------------- 1 | # Github 2 | 3 | Github es lo que se denomina una forja, un repositorio de proyectos que usan Git como sistema de control de versiones. Es la forja más popular, ya que alberga más de 10 millones de repositorios. Debe su popularidad a sus funcionalidades sociales, principalmente dos: la posibilidad de hacer forks de otros proyectos y la posibilidad de cooperar aportando código para arreglar errores o mejorar el código. Si bien, no es que fuera una novedad, sí lo es lo fácil que resulta hacerlo. A raíz de este proyecto han surgido otros como _Gitorius_ o _Gitlab_, pero _Github_ sigue siendo el más popular y el que tiene mejores y mayores características. algunas de estas son: 4 | 5 | - Un wiki para documentar el proyecto, que usa MarkDown como lenguaje de marca. 6 | - Un portal web para cada proyecto. 7 | - Funcionalidades de redes sociales como followers. 8 | - Gráficos estadísticos. 9 | - Revisión de código y comentarios. 10 | - Sistemas de seguimiento de incidencias. 11 | 12 | Lo primero es entrar en el portal ([https://github.com/](https://github.com/)) para crearnos una cuenta si no la tenemos aún. 13 | 14 | ## Tu clave pública/privada 15 | 16 | Muchos servidores Git utilizan la autentificación a través de claves públicas SSH. Y, para ello, cada usuario del sistema ha de generarse una, si es que no la tiene ya. El proceso para hacerlo es similar en casi cualquier sistema operativo. Ante todo, asegurarte que no tengas ya una clave. (comprueba que el directorio `$HOME/usuario/.ssh` no tiene un archivo id_dsa.pub o id_rsa.pub). 17 | 18 | Para crear una nueva clave usamos la siguiente orden: 19 | 20 | $ ssh-keygen -t rsa -C "Cuenta Thinstation" 21 | 22 | !!! warning 23 | 24 | Tu clave RSA te identifica contra los repositorios remotos, asegúrate de 25 | no compartir la clave privada con nadie. Por defecto la clave se crea como 26 | _solo lectura_. 27 | 28 | ## Configuración 29 | 30 | Vamos a aprovechar para añadir la clave RSA que generamos antes, para poder acceder desde git a los repositorios. Para ellos nos vamos al menú de configuración de usuario (_Settings_) 31 | 32 | ![Barra principal de menú](images/github-topbar.png) 33 | 34 | Nos vamos al menú 'SSH and GPG Keys' y añadimos una nueva clave. En _Title_ indicamos una descripción que nos ayude a saber de dónde procede la clave y en key volcamos el contenido del archivo `~/.ssh/id_rsa.pub`. Y guardamos la clave. 35 | 36 | ![Clave SSH](images/github-sshkeys.png) 37 | 38 | Con esto ya tendriamos todo nuestro entorno para poder empezar a trabajar desde nuestro equipo. 39 | 40 | ## Clientes gráficos para GitHub 41 | 42 | Además, para Github existe un cliente propio tanto para Windows como para MacOSX: 43 | 44 | - Cliente Windows: [http://windows.github.com/](http://windows.github.com/) 45 | 46 | - Cliente MacOSX: [http://mac.github.com/](http://mac.github.com/) 47 | 48 | Para Linux no hay cliente propio, pero sí hay plugin para la mayoría de editores de texto como atom, netbeans, eclipe o los editores de jetbrains. 49 | 50 | De todas maneras, estos clientes solo tienen el fin de facilitar el uso de Github, pero no son necesarios para usarlo. Es perfectamente válido usar el cliente de consola de Git o cualquier otro cliente genérico para Git. Uno de los más usados actualmente es [GitKraken](https://www.gitkraken.com/). 51 | 52 | ## Crear un repositorio 53 | 54 | Vamos a crear un repositorio donde guardar nuestro proyecto. Para ello pulsamos el signo `+` que hay en la barra superior y seleccionamos `New repository`. 55 | 56 | Ahora tenemos que designar un nombre para nuestro repositorio, por ejemplo: '_taller-de-git_'. 57 | 58 | ![Nuevo repositorio](images/github-newrepo.png) 59 | 60 | Nada más crear el repositorio nos saldrá una pantalla con instrucciones precisas de como proceder a continuación. 61 | 62 | Básicamente podemos partir de tres situaciones: 63 | 64 | 1. Todavía no hemos creado ningún repositorio en nuestro equipo. 65 | 1. Ya tenemos un repositorio creado y queremos sincronizarlo con Github. 66 | 1. Queremos importar un repositorio de otro sistema de control de versiones distinto. 67 | 68 | ![Quick setup](images/github-quicksetup.png) 69 | 70 | Nuestra situación es la segunda, así que nos aseguramos de que hemos elegido SSH como protocolo. A continuación pulsamos el icono del portapapeles y ejecutamos las dos ordenes que nos indica la web en nuestro terminal. 71 | 72 | $ git remote add origin git@github.com:sgomez/taller-de-git.git 73 | $ git push -u origin main 74 | Counting objects: 33, done. 75 | Delta compression using up to 4 threads. 76 | Compressing objects: 100% (24/24), done. 77 | Writing objects: 100% (33/33), 3.35 KiB | 1.12 MiB/s, done. 78 | Total 33 (delta 2), reused 0 (delta 0) 79 | remote: Resolving deltas: 100% (2/2), done. 80 | To github.com:sgomez/taller-de-git.git 81 | * [new branch] main -> main 82 | Branch main set up to track remote branch main from origin by rebasing. 83 | 84 | Si recargamos la página veremos que ya aparece nuestro proyecto. 85 | 86 | ![Github: código](images/github-code.png) 87 | 88 | ## Crear una clave SSH 89 | 90 | Muchos servidores Git utilizan la autentificación a través de claves públicas SSH. Y, para ello, cada usuario del sistema ha de generarse una, si es que no la tiene ya. El proceso para hacerlo es similar en casi cualquier sistema operativo. Ante todo, asegurarte que no tengas ya una clave. (comprueba que el directorio `$HOME/usuario/.ssh` no tiene un archivo id_dsa.pub o id_rsa.pub). 91 | 92 | Para crear una nueva clave usamos la siguiente orden: 93 | 94 | ```bash 95 | ssh-keygen -t ed25519 -C "Mi ordenador personal" 96 | ``` 97 | 98 | !!! warning 99 | Ejecuta la orden anterior solo si no tenias ya una clave creada. 100 | 101 | Tu clave RSA te identifica contra los repositorios remotos, asegúrate de 102 | no compartir la clave privada con nadie. Por defecto la clave se crea como 103 | _solo lectura_. 104 | 105 | En la web de [Github tienes una documetación más detallada](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/checking-for-existing-ssh-keys). 106 | 107 | 108 | ## Clonar un repositorio 109 | 110 | Una vez que ya tengamos sincronizado el repositorio contra Github, eventualmente 111 | vamos a querer descargarlo en otro de nuestros ordenadores para poder trabajar 112 | en él. Esta acción se denomina clonar y para ello usaremos la orden `git clone`. 113 | 114 | En la página principal de nuestro proyecto podemos ver un botón que indica `Clone or download`. 115 | Si la pulsamos nos da, de nuevo, la opción de elegir entre clonar con _ssh_ o _https_. 116 | 117 | Para clonar nuestro repositorio y poder trabajar con él todo lo que debemos hacer es 118 | lo siguiente: 119 | 120 | $ git clone git@github.com:sgomez/taller-de-git.git 121 | $ cd taller-de-git 122 | 123 | ## Ramas remotas 124 | 125 | Si ahora vemos el estado de nuestro proyecto veremos algo similar a esto: 126 | 127 | ``` 128 | $ git hist --all 129 | * 2eab8ca 2013-06-16 | Aplicando los cambios de la rama hola (HEAD -> main, origin/main) [Sergio Gomez] 130 | *\ 131 | | * 9862f33 2013-06-16 | hola usa la clase HolaMundo (hola) [Sergio Gómez] 132 | | * 6932156 2013-06-16 | Añadida la clase HolaMundo [Sergio Gómez] 133 | |/ 134 | * 9c85275 2013-06-16 | Programa interactivo (main) [Sergio Gómez] 135 | * c3e65d0 2013-06-16 | Añadido README.md [Sergio Gómez] 136 | * 81c6e93 2013-06-16 | Movido hola.php a lib [Sergio Gómez] 137 | * 96a39df 2013-06-16 | Añadido el autor del programa y su email [Sergio Gómez] 138 | * fd4da94 2013-06-16 | Se añade un comentario al cambio del valor por defecto (tag: v1) [Sergio Gómez] 139 | * 3283e0d 2013-06-16 | Se añade un parámetro por defecto (tag: v1-beta) [Sergio Gómez] 140 | * efc252e 2013-06-16 | Parametrización del programa [Sergio Gómez] 141 | * e19f2c1 2013-06-16 | Creación del proyecto [Sergio Gómez] 142 | ``` 143 | 144 | Aparece que hay una nueva rama llamada `origin/main`. Esta rama indica el estado de sincronización 145 | de nuestro repositorio con un repositorio remoto llamado _origin_. En este caso el de _Github_. 146 | 147 | !!! info 148 | 149 | Por norma se llama automáticamente _origin_ al primer repositorio con el que 150 | sincronizamos nuestro repositorio. 151 | 152 | Podemos ver la configuración de este repositorio remoto con la orden `git remote`: 153 | 154 | $ git remote show origin 155 | * remote origin 156 | Fetch URL: git@github.com:sgomez/taller-de-git.git 157 | Push URL: git@github.com:sgomez/taller-de-git.git 158 | HEAD branch: main 159 | Remote branch: 160 | main tracked 161 | Local ref configured for 'git push': 162 | main pushes to main (up to date) 163 | 164 | De la respuesta tenemos que fijarnos en las líneas que indican _fetch_ y _push_ 165 | puesto que son las acciones de sincronización de nuestro repositorio con el remoto. 166 | Mientras que _fetch_ se encarga de traer los cambios desde el repositorio remoto 167 | al nuestro, _push_ los envía. 168 | 169 | ## Enviando actualizaciones 170 | 171 | Vamos a añadir una licencia a nuestra aplicación. Creamos un fichero LICENSE con el siguiente contenido: 172 | 173 | ``` 174 | MIT License 175 | 176 | Copyright (c) [year] [fullname] 177 | 178 | Permission is hereby granted, free of charge, to any person obtaining a copy 179 | of this software and associated documentation files (the "Software"), to deal 180 | in the Software without restriction, including without limitation the rights 181 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 182 | copies of the Software, and to permit persons to whom the Software is 183 | furnished to do so, subject to the following conditions: 184 | 185 | The above copyright notice and this permission notice shall be included in all 186 | copies or substantial portions of the Software. 187 | 188 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 189 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 190 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 191 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 192 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 193 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 194 | SOFTWARE. 195 | ``` 196 | 197 | Y añadidos y confirmamos los cambios: 198 | 199 | ``` 200 | $ git add LICENSE 201 | $ git commit -m "Añadida licencia" 202 | [main 3f5cb1c] Añadida licencia 203 | 1 file changed, 21 insertions(+) 204 | create mode 100644 LICENSE 205 | $ git hist --all 206 | * 3f5cb1c 2013-06-16 | Añadida licencia (HEAD -> main) [Sergio Gómez] 207 | * 2eab8ca 2013-06-16 | Aplicando los cambios de la rama hola (origin/main) [Sergio Gomez] 208 | *\ 209 | | * 9862f33 2013-06-16 | hola usa la clase HolaMundo (hola) [Sergio Gómez] 210 | | * 6932156 2013-06-16 | Añadida la clase HolaMundo [Sergio Gómez] 211 | |/ 212 | * 9c85275 2013-06-16 | Programa interactivo (main) [Sergio Gómez] 213 | * c3e65d0 2013-06-16 | Añadido README.md [Sergio Gómez] 214 | * 81c6e93 2013-06-16 | Movido hola.php a lib [Sergio Gómez] 215 | * 96a39df 2013-06-16 | Añadido el autor del programa y su email [Sergio Gómez] 216 | * fd4da94 2013-06-16 | Se añade un comentario al cambio del valor por defecto (tag: v1) [Sergio Gómez] 217 | * 3283e0d 2013-06-16 | Se añade un parámetro por defecto (tag: v1-beta) [Sergio Gómez] 218 | * efc252e 2013-06-16 | Parametrización del programa [Sergio Gómez] 219 | * e19f2c1 2013-06-16 | Creación del proyecto [Sergio Gómez] 220 | ``` 221 | 222 | Viendo la historia podemos ver como nuestro main no está en el mismo punto que 223 | `origin/main`. Si vamos a la web de _Github_ veremos que `LICENSE` no aparece aún. 224 | Así que vamos a enviar los cambios con la primera de las acciones que vimos `git push`: 225 | 226 | $ git push -u origin main 227 | Counting objects: 3, done. 228 | Delta compression using up to 4 threads. 229 | Compressing objects: 100% (3/3), done. 230 | Writing objects: 100% (3/3), 941 bytes | 0 bytes/s, done. 231 | Total 3 (delta 0), reused 0 (delta 0) 232 | To git@github.com:sgomez/taller-de-git.git 233 | 2eab8ca..3f5cb1c main -> main 234 | Branch main set up to track remote branch main from origin. 235 | 236 | !!! info 237 | 238 | La orden `git push` necesita dos parámetros para funcionar: el repositorio 239 | y la rama destino. Así que realmente lo que teníamos que haber escrito es: 240 | 241 | $ git push origin main 242 | 243 | Para ahorrar tiempo escribiendo _git_ nos deja vincular nuestra rama local 244 | con una rama remota, de tal manera que no tengamos que estar siempre indicándolo. 245 | Eso es posible con el parámetro `--set-upstream` o `-u` en forma abreviada. 246 | 247 | $ git push -u origin main 248 | 249 | Si repasas las órdenes que te indicó Github que ejecutaras verás que el parámetro 250 | `-u` estaba presente y por eso no ha sido necesario indicar ningún parámetro 251 | al hacer push. 252 | 253 | ## Recibiendo actualizaciones 254 | 255 | Si trabajamos con más personas, o trabajamos desde dos ordenadores distintos, nos encontraremos 256 | con que nuestro repositorio local es más antiguo que el remoto. Necesitamos descargar 257 | los cambios para poder incorporarlos a nuestro directorio de trabajo. 258 | 259 | Para la prueba, Github nos permite editar archivos directamente desde la web. Pulsamos sobre 260 | el archivo `README.md`. En la vista del archivo, veremos que aparece el icono de un lápiz. 261 | Esto nos permite editar el archivo. 262 | 263 | ![Editar archivo](images/github-edit.png) 264 | 265 | !!! info 266 | 267 | Los archivos con extensión `.md` están en un formato denominado _MarkDown_. Se trata 268 | de un lenguaje de marca que nos permite escribir texto enriquecido de manera muy sencilla. 269 | 270 | Dispones de un tutorial aquí: [https://www.markdowntutorial.com/](https://www.markdowntutorial.com/) 271 | 272 | Modificamos el archivo como queramos, por ejemplo, añadiendo nuestro nombre: 273 | 274 | ``` 275 | # Curso de GIT 276 | 277 | Este proyecto contiene el curso de introducción a GIT 278 | 279 | Desarrollado por Sergio Gómez. 280 | ``` 281 | 282 | ![Confirmar cambios](images/github-changes.png) 283 | 284 | El cambio quedará incorporado al repositorio de Github, pero no al nuestro. Necesitamos 285 | traer la información desde el servidor remoto. La orden asociada es `git fetch`: 286 | 287 | ``` 288 | $ git fetch 289 | $ git hist --all 290 | * cbaf831 2013-06-16 | Actualizado README.md (origin/main) [Sergio Gómez] 291 | * 3f5cb1c 2013-06-16 | Añadida licencia (HEAD -> main) [Sergio Gómez] 292 | * 2eab8ca 2013-06-16 | Aplicando los cambios de la rama hola [Sergio Gomez] 293 | *\ 294 | | * 9862f33 2013-06-16 | hola usa la clase HolaMundo (hola) [Sergio Gómez] 295 | | * 6932156 2013-06-16 | Añadida la clase HolaMundo [Sergio Gómez] 296 | |/ 297 | * 9c85275 2013-06-16 | Programa interactivo (main) [Sergio Gómez] 298 | * c3e65d0 2013-06-16 | Añadido README.md [Sergio Gómez] 299 | * 81c6e93 2013-06-16 | Movido hola.php a lib [Sergio Gómez] 300 | * 96a39df 2013-06-16 | Añadido el autor del programa y su email [Sergio Gómez] 301 | * fd4da94 2013-06-16 | Se añade un comentario al cambio del valor por defecto (tag: v1) [Sergio Gómez] 302 | * 3283e0d 2013-06-16 | Se añade un parámetro por defecto (tag: v1-beta) [Sergio Gómez] 303 | * efc252e 2013-06-16 | Parametrización del programa [Sergio Gómez] 304 | * e19f2c1 2013-06-16 | Creación del proyecto [Sergio Gómez] 305 | ``` 306 | 307 | Ahora vemos el caso contrario, tenemos que `origin/main` está por delante que `HEAD` y 308 | que la rama `main` local. 309 | 310 | Ahora necesitamos incorporar los cambios de la rama remota en la local. La forma de hacerlo 311 | lo vimos en el [capítulo anterior](ramas.md#mezclar-ramas) usando `git merge` o `git rebase`. 312 | 313 | Habitualmente se usa `git merge`: 314 | 315 | ``` 316 | $ git merge origin/main 317 | Updating 3f5cb1c..cbaf831 318 | Fast-forward 319 | README.md | 2 ++ 320 | 1 file changed, 2 insertions(+) 321 | $ git hist --all 322 | * cbaf831 2013-06-16 | Actualizado README.md (HEAD -> main, origin/main) [Sergio Gómez] 323 | * 3f5cb1c 2013-06-16 | Añadida licencia [Sergio Gómez] 324 | * 2eab8ca 2013-06-16 | Aplicando los cambios de la rama hola [Sergio Gomez] 325 | *\ 326 | | * 9862f33 2013-06-16 | hola usa la clase HolaMundo (hola) [Sergio Gómez] 327 | | * 6932156 2013-06-16 | Añadida la clase HolaMundo [Sergio Gómez] 328 | |/ 329 | * 9c85275 2013-06-16 | Programa interactivo (main) [Sergio Gómez] 330 | * c3e65d0 2013-06-16 | Añadido README.md [Sergio Gómez] 331 | * 81c6e93 2013-06-16 | Movido hola.php a lib [Sergio Gómez] 332 | * 96a39df 2013-06-16 | Añadido el autor del programa y su email [Sergio Gómez] 333 | * fd4da94 2013-06-16 | Se añade un comentario al cambio del valor por defecto (tag: v1) [Sergio Gómez] 334 | * 3283e0d 2013-06-16 | Se añade un parámetro por defecto (tag: v1-beta) [Sergio Gómez] 335 | * efc252e 2013-06-16 | Parametrización del programa [Sergio Gómez] 336 | * e19f2c1 2013-06-16 | Creación del proyecto [Sergio Gómez] 337 | ``` 338 | 339 | Como las operaciones de traer cambios (`git fetch`) y de mezclar ramas (`git merge` o `git rebase`) 340 | están muy asociadas, _git_ nos ofrece una posibilidad para ahorrar pasos que es la orden `git pull` 341 | que realiza las dos acciones simultáneamente. 342 | 343 | Para probar, vamos a editar de nuevo el archivo README.md y añadimos algo más: 344 | 345 | ``` 346 | # Curso de GIT 347 | 348 | Este proyecto contiene el curso de introducción a GIT del Aula de Software Libre. 349 | 350 | Desarrollado por Sergio Gómez. 351 | ``` 352 | 353 | Como mensaje del _commit_: _'Indicado que se realiza en el ASL'_. 354 | 355 | Y ahora probamos a actualizar con `git pull`: 356 | 357 | ``` 358 | $ git pull 359 | remote: Counting objects: 3, done. 360 | remote: Compressing objects: 100% (3/3), done. 361 | remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 362 | Unpacking objects: 100% (3/3), done. 363 | From github.com:sgomez/taller-de-git 364 | cbaf831..d8922e4 main -> origin/main 365 | First, rewinding head to replay your work on top of it... 366 | Fast-forwarded main to d8922e4ffa4f87553b03e77df6196b7e496bfec4. 367 | $ git hist --all 368 | * d8922e4 2013-06-16 | Indicado que se realiza en el ASL (HEAD -> main, origin/main) [Sergio Gómez] 369 | * cbaf831 2013-06-16 | Actualizado README.md [Sergio Gómez] 370 | * 3f5cb1c 2013-06-16 | Añadida licencia [Sergio Gómez] 371 | * 2eab8ca 2013-06-16 | Aplicando los cambios de la rama hola [Sergio Gomez] 372 | *\ 373 | | * 9862f33 2013-06-16 | hola usa la clase HolaMundo (hola) [Sergio Gómez] 374 | | * 6932156 2013-06-16 | Añadida la clase HolaMundo [Sergio Gómez] 375 | |/ 376 | * 9c85275 2013-06-16 | Programa interactivo (main) [Sergio Gómez] 377 | * c3e65d0 2013-06-16 | Añadido README.md [Sergio Gómez] 378 | * 81c6e93 2013-06-16 | Movido hola.php a lib [Sergio Gómez] 379 | * 96a39df 2013-06-16 | Añadido el autor del programa y su email [Sergio Gómez] 380 | * fd4da94 2013-06-16 | Se añade un comentario al cambio del valor por defecto (tag: v1) [Sergio Gómez] 381 | * 3283e0d 2013-06-16 | Se añade un parámetro por defecto (tag: v1-beta) [Sergio Gómez] 382 | * efc252e 2013-06-16 | Parametrización del programa [Sergio Gómez] 383 | * e19f2c1 2013-06-16 | Creación del proyecto [Sergio Gómez] 384 | ``` 385 | 386 | Vemos que los cambios se han incorporado y que las ramas remota y local de _main_ están 387 | sincronizadas. 388 | 389 | ## Problemas de sincronización 390 | 391 | ### No puedo hacer push 392 | 393 | Al intentar subir cambios nos podemos encontrar un mensaje como este: 394 | 395 | ``` 396 | $ git push 397 | git push 398 | To git@github.com:sgomez/taller-de-git.git 399 | ! [rejected] main -> main (fetch first) 400 | error: failed to push some refs to 'git@github.com:sgomez/taller-de-git.git' 401 | hint: Updates were rejected because the remote contains work that you do 402 | hint: not have locally. This is usually caused by another repository pushing 403 | hint: to the same ref. You may want to first integrate the remote changes 404 | hint: (e.g., 'git pull ...') before pushing again. 405 | hint: See the 'Note about fast-forwards' in 'git push --help' for details. 406 | ``` 407 | 408 | La causa es que el repositorio remoto también se ha actualizado y nosotros aún 409 | no hemos recibido esos cambios. Es decir, ambos repositorios se han actualizado 410 | y el remoto tiene preferencia. Hay un conflicto en ciernes y se debe resolver 411 | localmente antes de continuar. 412 | 413 | Vamos a provocar una situación donde podamos ver esto en acción. Vamos a modificar el 414 | archivo `README.md` tanto en local como en remoto a través del interfaz web. 415 | 416 | En el web vamos a cambiar el título para que aparezca de la siguiente manera. 417 | 418 | Curso de GIT, 2020 419 | 420 | En local vamos a cambiar el título para que aparezca de la siguiente manera. 421 | 422 | Curso de GIT, febrero 423 | 424 | !!! question 425 | 426 | Haz el commit para guardar el cambio en local. 427 | 428 | ??? example "Respuesta al ejercicio anterior" 429 | 430 | Añadimos el fichero actualizado: 431 | 432 | $ git commit -am "Añadido el mes al README" 433 | [main 1e8c0b7] Añadido el mes al README 434 | 1 file changed, 1 insertion(+), 1 deletion(-) 435 | 436 | La forma de proceder en este caso es hacer un `git fetch` y un `git rebase`. Si 437 | hay conflictos deberán resolverse. Cuando esté todo solucionado ya podremos hacer 438 | `git push`. 439 | 440 | !!! info 441 | 442 | Por defecto `git pull` lo que hace es un `git merge`, si queremos hacer 443 | `git rebase` deberemos especificarlos con el parámetro `-r`: 444 | 445 | $ git pull --rebase 446 | 447 | Vamos a hacer el pull con rebase y ver qué sucede. 448 | 449 | $ git pull --rebase 450 | First, rewinding head to replay your work on top of it... 451 | Applying: Añadido el mes al README 452 | Using index info to reconstruct a base tree... 453 | M README.md 454 | Falling back to patching base and 3-way merge... 455 | Auto-merging README.md 456 | CONFLICT (content): Merge conflict in README.md 457 | error: Failed to merge in the changes. 458 | Patch failed at 0001 Añadido el mes al README 459 | hint: Use 'git am --show-current-patch' to see the failed patch 460 | 461 | Resolve all conflicts manually, mark them as resolved with 462 | "git add/rm ", then run "git rebase --continue". 463 | You can instead skip this commit: run "git rebase --skip". 464 | To abort and get back to the state before "git rebase", run "git rebase --abort". 465 | 466 | Evidentemente hay un conflicto porque hemos tocado el mismo archivo. Se deja como ejercicio resolverlo. 467 | 468 | ??? example "Respuesta al ejercicio anterior" 469 | 470 | El contenido del fichero final podría ser: 471 | 472 | Curso de GIT, febrero, 2020 473 | 474 | A continuación confirmamos los cambios y los enviamos al servidor 475 | 476 | $ git add README.md 477 | $ git rebase --continue 478 | $ git push 479 | 480 | !!! warning 481 | 482 | ¿Por qué hemos hecho rebase en main si a lo largo del curso hemos dicho que no se debe cambiar 483 | la linea principal? 484 | 485 | Básicamente hemos dicho que lo que no debemos hacer es modificar la línea temporal **compartida**. 486 | En este caso nuestros cambios en _main_ solo estaban en nuestro repositorio, porque al fallar 487 | el envío nadie más ha visto nuestras actualizaciones. Al hacer _rebase_ estamos deshaciendo nuestros 488 | cambios, bajarnos la última actualización compartida de _main_ y volviéndolos a aplicar. Con lo que 489 | realmente la historia compartida no se ha modificado. 490 | 491 | Este es un problema que debemos evitar en la medida de lo posible. La menor cantidad 492 | de gente posible debe tener acceso de escritura en main y las actualizaciones de dicha rama deben 493 | hacerse a través de ramas secundarias y haciendo merge en main como hemos visto en el capítulo de ramas. 494 | 495 | ### No puedo hacer pull 496 | 497 | Al intentar descargar cambios nos podemos encontrar un mensaje como este: 498 | 499 | $ git pull 500 | error: Cannot pull with rebase: You have unstaged changes. 501 | 502 | O como este: 503 | 504 | $ git pull 505 | error: Cannot pull with rebase: Your index contains uncommitted changes. 506 | 507 | Básicamente lo que ocurre es que tenemos cambios sin confirmar en nuestro espacio 508 | de trabajo. Una opción es confirmar (_commit_) y entonces proceder como el caso anterior. 509 | 510 | Pero puede ocurrir que aún estemos trabajando todavía y no nos interese confirmar 511 | los cambios, solo queremos sincronizar y seguir trabajando. Para casos como estos 512 | _git_ ofrece una pila para guardar cambios temporalmente. Esta pila se llama _stash_ 513 | y nos permite restaurar el espacio de trabajo al último commit. 514 | 515 | De nuevo vamos a modificar nuestro proyecto para ver esta situación en acción. 516 | 517 | !!! example 518 | 519 | En remoto borra el año de la fecha y en local borra el mes. Pero esta vez 520 | **no hagas commit en local**. El archivo solo debe quedar modificado. 521 | 522 | La forma de proceder es la siguiente: 523 | 524 | ``` 525 | $ git stash save # Guardamos los cambios en la pila 526 | $ git pull # Sincronizamos con el repositorio remoto, -r para hacer rebase puede ser requerido 527 | $ git stash pop # Sacamos los cambios de la pila 528 | ``` 529 | 530 | !!! info 531 | 532 | Como ocurre habitualmente, git nos proporciona una forma de hacer todos estos pasos de una 533 | sola vez. Para ello tenemos que ejecutar lo siguiente: 534 | 535 | $ git pull --autostash 536 | 537 | En general no es mala idea ejecutar lo siguiente si somos conscientes, además, de que tenemos varios 538 | cambios sin sincronizar: 539 | 540 | $ git pull --autostash --rebase 541 | 542 | Podría darse el caso de que al sacar los cambios de la pila hubiera algún 543 | conflicto. En ese caso actuamos como con el caso de _merge_ o _rebase_. 544 | 545 | De nuevo este tipo de problemas no deben suceder si nos acostumbramos a trabajar en ramas. 546 | -------------------------------------------------------------------------------- /docs/images/distribuido-git.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aulasoftwarelibre/taller-de-git/750ed3ff100dc315660aa97650aa89788b73081f/docs/images/distribuido-git.png -------------------------------------------------------------------------------- /docs/images/distribuido-tradicional.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aulasoftwarelibre/taller-de-git/750ed3ff100dc315660aa97650aa89788b73081f/docs/images/distribuido-tradicional.png -------------------------------------------------------------------------------- /docs/images/flujo-centralizado.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aulasoftwarelibre/taller-de-git/750ed3ff100dc315660aa97650aa89788b73081f/docs/images/flujo-centralizado.png -------------------------------------------------------------------------------- /docs/images/flujo-dictador.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aulasoftwarelibre/taller-de-git/750ed3ff100dc315660aa97650aa89788b73081f/docs/images/flujo-dictador.png -------------------------------------------------------------------------------- /docs/images/flujo-integracion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aulasoftwarelibre/taller-de-git/750ed3ff100dc315660aa97650aa89788b73081f/docs/images/flujo-integracion.png -------------------------------------------------------------------------------- /docs/images/git-central.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aulasoftwarelibre/taller-de-git/750ed3ff100dc315660aa97650aa89788b73081f/docs/images/git-central.png -------------------------------------------------------------------------------- /docs/images/git-distrib.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aulasoftwarelibre/taller-de-git/750ed3ff100dc315660aa97650aa89788b73081f/docs/images/git-distrib.png -------------------------------------------------------------------------------- /docs/images/git-estados.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aulasoftwarelibre/taller-de-git/750ed3ff100dc315660aa97650aa89788b73081f/docs/images/git-estados.png -------------------------------------------------------------------------------- /docs/images/git-local.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aulasoftwarelibre/taller-de-git/750ed3ff100dc315660aa97650aa89788b73081f/docs/images/git-local.png -------------------------------------------------------------------------------- /docs/images/github-changes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aulasoftwarelibre/taller-de-git/750ed3ff100dc315660aa97650aa89788b73081f/docs/images/github-changes.png -------------------------------------------------------------------------------- /docs/images/github-code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aulasoftwarelibre/taller-de-git/750ed3ff100dc315660aa97650aa89788b73081f/docs/images/github-code.png -------------------------------------------------------------------------------- /docs/images/github-edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aulasoftwarelibre/taller-de-git/750ed3ff100dc315660aa97650aa89788b73081f/docs/images/github-edit.png -------------------------------------------------------------------------------- /docs/images/github-flow-merge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aulasoftwarelibre/taller-de-git/750ed3ff100dc315660aa97650aa89788b73081f/docs/images/github-flow-merge.png -------------------------------------------------------------------------------- /docs/images/github-flow-merged.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aulasoftwarelibre/taller-de-git/750ed3ff100dc315660aa97650aa89788b73081f/docs/images/github-flow-merged.png -------------------------------------------------------------------------------- /docs/images/github-flow-pr-created.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aulasoftwarelibre/taller-de-git/750ed3ff100dc315660aa97650aa89788b73081f/docs/images/github-flow-pr-created.png -------------------------------------------------------------------------------- /docs/images/github-flow-pr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aulasoftwarelibre/taller-de-git/750ed3ff100dc315660aa97650aa89788b73081f/docs/images/github-flow-pr.png -------------------------------------------------------------------------------- /docs/images/github-issues-list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aulasoftwarelibre/taller-de-git/750ed3ff100dc315660aa97650aa89788b73081f/docs/images/github-issues-list.png -------------------------------------------------------------------------------- /docs/images/github-issues-new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aulasoftwarelibre/taller-de-git/750ed3ff100dc315660aa97650aa89788b73081f/docs/images/github-issues-new.png -------------------------------------------------------------------------------- /docs/images/github-main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aulasoftwarelibre/taller-de-git/750ed3ff100dc315660aa97650aa89788b73081f/docs/images/github-main.png -------------------------------------------------------------------------------- /docs/images/github-mergerequest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aulasoftwarelibre/taller-de-git/750ed3ff100dc315660aa97650aa89788b73081f/docs/images/github-mergerequest.png -------------------------------------------------------------------------------- /docs/images/github-newrepo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aulasoftwarelibre/taller-de-git/750ed3ff100dc315660aa97650aa89788b73081f/docs/images/github-newrepo.png -------------------------------------------------------------------------------- /docs/images/github-proyect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aulasoftwarelibre/taller-de-git/750ed3ff100dc315660aa97650aa89788b73081f/docs/images/github-proyect.png -------------------------------------------------------------------------------- /docs/images/github-pullconversation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aulasoftwarelibre/taller-de-git/750ed3ff100dc315660aa97650aa89788b73081f/docs/images/github-pullconversation.png -------------------------------------------------------------------------------- /docs/images/github-pullrequest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aulasoftwarelibre/taller-de-git/750ed3ff100dc315660aa97650aa89788b73081f/docs/images/github-pullrequest.png -------------------------------------------------------------------------------- /docs/images/github-pushed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aulasoftwarelibre/taller-de-git/750ed3ff100dc315660aa97650aa89788b73081f/docs/images/github-pushed.png -------------------------------------------------------------------------------- /docs/images/github-quicksetup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aulasoftwarelibre/taller-de-git/750ed3ff100dc315660aa97650aa89788b73081f/docs/images/github-quicksetup.png -------------------------------------------------------------------------------- /docs/images/github-sshkeys.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aulasoftwarelibre/taller-de-git/750ed3ff100dc315660aa97650aa89788b73081f/docs/images/github-sshkeys.png -------------------------------------------------------------------------------- /docs/images/github-topbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aulasoftwarelibre/taller-de-git/750ed3ff100dc315660aa97650aa89788b73081f/docs/images/github-topbar.png -------------------------------------------------------------------------------- /docs/images/gitlab-dashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aulasoftwarelibre/taller-de-git/750ed3ff100dc315660aa97650aa89788b73081f/docs/images/gitlab-dashboard.png -------------------------------------------------------------------------------- /docs/images/gitlab-merge-ff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aulasoftwarelibre/taller-de-git/750ed3ff100dc315660aa97650aa89788b73081f/docs/images/gitlab-merge-ff.png -------------------------------------------------------------------------------- /docs/images/gitlab-mergerequest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aulasoftwarelibre/taller-de-git/750ed3ff100dc315660aa97650aa89788b73081f/docs/images/gitlab-mergerequest.png -------------------------------------------------------------------------------- /docs/images/gitlab-organizacion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aulasoftwarelibre/taller-de-git/750ed3ff100dc315660aa97650aa89788b73081f/docs/images/gitlab-organizacion.png -------------------------------------------------------------------------------- /docs/images/gitlab-proyecto.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aulasoftwarelibre/taller-de-git/750ed3ff100dc315660aa97650aa89788b73081f/docs/images/gitlab-proyecto.png -------------------------------------------------------------------------------- /docs/images/logo-cuadrado-invertido.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | 51 | 53 | 55 | 56 | 58 | image/svg+xml 59 | 61 | 62 | 63 | 64 | 65 | 71 | 73 | 76 | 79 | 80 | 82 | 89 | 94 | 98 | 102 | 106 | 110 | 111 | 116 | 120 | 124 | 128 | 132 | 136 | 137 | 142 | 146 | 150 | 154 | 158 | 159 | 164 | 168 | 172 | 173 | 178 | 182 | 183 | 189 | 194 | 195 | 196 | 197 | 198 | -------------------------------------------------------------------------------- /docs/images/logoasl-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aulasoftwarelibre/taller-de-git/750ed3ff100dc315660aa97650aa89788b73081f/docs/images/logoasl-white.png -------------------------------------------------------------------------------- /docs/images/logoasl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aulasoftwarelibre/taller-de-git/750ed3ff100dc315660aa97650aa89788b73081f/docs/images/logoasl.png -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # Inicio 2 | 3 | ![Aula Software Libre de la UCO](images/logo-cuadrado-invertido.svg) 4 | 5 | Este taller forma parte de las actividades del [Aula de Software Libre de la 6 | Universidad de Córdoba](https://www.uco.es/aulasoftwarelibre). 7 | 8 | El contenido del mismo es en parte de producción propia, en parte de otros 9 | manuales libres que pueden encontrarse en la sección de [Referencias](referencias.md). 10 | 11 | ## Contenido 12 | 13 | - Inicio 14 | - Sistemas de control de versiones 15 | - Introducción a Git 16 | - Aspectos básicos de Git 17 | - Uso básico 18 | - Uso avanzado 19 | - Ramas 20 | - Administración de repositorios 21 | - Flujo de trabajo con Git (git flow) 22 | - Github 23 | - Referencias 24 | 25 | ## Agradecimientos 26 | 27 | Este curso ha sido impartido por las siguientes personas: 28 | 29 | - [Adrián López](https://github.com/AdrianLopezGue) 30 | - [Héctor Romero](https://github.com/cyberh99) 31 | - [Javier de Santiago](https://github.com/jdes01) 32 | - [José Márquez](https://github.com/IronSenior) 33 | - [Sergio Gómez](https://github.com/sgomez) 34 | - [Alba Palomino](https://github.com/Albapj01) 35 | 36 | ## Licencia 37 | 38 | El material está publicado con licencia [Atribución-NoComercial 4.0 Internacional (CC BY-NC 4.0)](https://creativecommons.org/licenses/by-nc/4.0/deed.es) 39 | -------------------------------------------------------------------------------- /docs/introduccion.md: -------------------------------------------------------------------------------- 1 | # Introducción a git 2 | 3 | Git es un sistema de control de versiones distribuido que se diferencia del resto en el modo en que modela sus datos. La mayoría de los demás sistemas almacenan la información como una lista de cambios en los archivos, mientras que Git modela sus datos más como un conjunto de instantáneas de un mini sistema de archivos. 4 | 5 | ![Modelo de datos de los sistemas distribuidos tradicionales](images/distribuido-tradicional.png) 6 | 7 | ![Modelo de datos de Git](images/distribuido-git.png) 8 | 9 | ## Los tres estados 10 | 11 | Git tiene tres estados principales en los que se pueden encontrar tus archivos: confirmado (committed), modificado (modified), y preparado (staged). Confirmado significa que los datos están almacenados de manera segura en tu base de datos local. Modificado significa que has modificado el archivo pero todavía no lo has confirmado a tu base de datos. Preparado significa que has marcado un archivo modificado en su versión actual para que vaya en tu próxima confirmación. 12 | 13 | Esto nos lleva a las tres secciones principales de un proyecto de Git: el directorio de Git (Git directory), el directorio de trabajo (working directory), y el área de preparación (staging area). 14 | 15 | ![ Directorio de trabajo, área de preparación, y directorio de Git ](images/git-estados.png) 16 | 17 | ## Flujos de trabajo distribuidos con git 18 | 19 | Hemos visto en qué consiste un entorno de control de versiones distribuido, pero más allá de la simple definición, existe más de una manera de gestionar los repositorios. Estos son los flujos de trabajo más comunes en Git. 20 | 21 | ### Flujo de trabajo centralizado 22 | 23 | Existe un único repositorio o punto central que guarda el código y todo el mundo sincroniza su trabajo con él. Si dos desarrolladores clonan desde el punto central, y ambos hacen cambios; tan solo el primero de ellos en enviar sus cambios de vuelta lo podrá hacer limpiamente. El segundo desarrollador deberá fusionar previamente su trabajo con el del primero, antes de enviarlo, para evitar el sobreescribir los cambios del primero 24 | 25 | ![ Flujo de trabajo centralizado ](images/flujo-centralizado.png) 26 | 27 | ### Flujo de trabajo del Gestor-de-Integraciones 28 | 29 | Al permitir múltiples repositorios remotos, en Git es posible tener un flujo de trabajo donde cada desarrollador tenga acceso de escritura a su propio repositorio público y acceso de lectura a los repositorios de todos los demás. Habitualmente, este escenario suele incluir un repositorio canónico, representante "oficial" del proyecto. 30 | 31 | ![ Flujo de trabajo del Gestor-de-Integraciones ](images/flujo-integracion.png) 32 | 33 | !!! info 34 | 35 | Este modelo se puso muy de moda a raíz de la forja GitHub que se verá más adelante. 36 | 37 | ### Flujo de trabajo con Dictador y Tenientes 38 | 39 | Es una variante del flujo de trabajo con múltiples repositorios. Se utiliza generalmente en proyectos muy grandes, con cientos de colaboradores. Un ejemplo muy conocido es el del kernel de Linux. Unos gestores de integración se encargan de partes concretas del repositorio; y se denominan tenientes. Todos los tenientes rinden cuentas a un gestor de integración; conocido como el dictador benevolente. El repositorio del dictador benevolente es el repositorio de referencia, del que recuperan (pull) todos los colaboradores. 40 | 41 | ![ Flujo de trabajo con Dictador y Tenientes ](images/flujo-dictador.png) 42 | -------------------------------------------------------------------------------- /docs/ramas.md: -------------------------------------------------------------------------------- 1 | # Ramas 2 | 3 | ## Administración de ramas 4 | 5 | ### Crear una nueva rama 6 | 7 | Cuando vamos a trabajar en una nueva funcionalidad, es conveniente hacerlo en una nueva rama, para no modificar la rama principal y dejarla inestable. Aunque la orden para manejar ramas es `git branch` podemos usar también `git checkout`. 8 | 9 | Vamos a crear una nueva rama: 10 | 11 | ``` 12 | git branch hola 13 | ``` 14 | 15 | ```mermaid 16 | gitGraph: 17 | commit id: "e19f2c1" 18 | commit id: "efc252e" 19 | commit id: "3283e0d" tag: "v1-beta" 20 | commit id: "fd4da94" tag: "v1" 21 | commit id: "96a39df" 22 | commit id: "8c2a509" 23 | branch hola 24 | ``` 25 | 26 | !!! info 27 | 28 | Si usamos `git branch` sin ningún argumento, nos devolverá la lista de ramas 29 | disponibles. 30 | 31 | La orden anterior no devuelve ningún resultado y tampoco nos cambia de rama, para eso 32 | debemos usar _checkout_: 33 | 34 | $ git checkout hola 35 | Switched to branch 'hola' 36 | 37 | !!! tip 38 | 39 | Hay una forma más rapida de hacer ambas acciones en un solo paso. Con el parámetro 40 | `-b` de `git checkout` podemos cambiarnos a una rama que, si no existe, se crea 41 | instantáneamente. 42 | 43 | $ git checkout -b hola 44 | Switched to a new branch 'hola' 45 | 46 | ### Modificaciones en la rama secundaria 47 | 48 | Añadimos un nuevo archivo en el directorio `lib` llamado `HolaMundo.php`: 49 | 50 | ```php 51 | nombre = $nombre; 60 | } 61 | 62 | function __toString() 63 | { 64 | return sprintf ("Hola, %s.\n", $this->nombre); 65 | } 66 | } 67 | ``` 68 | 69 | Y modificamos `hola.php`: 70 | 71 | ```php 72 | 74 | // El nombre por defecto es Mundo 75 | require('HolaMundo.php'); 76 | 77 | $nombre = isset($argv[1]) ? $argv[1] : "Mundo"; 78 | print new HolaMundo($nombre); 79 | ``` 80 | 81 | Podríamos confirmar los cambios todos de golpe, pero lo haremos de uno en uno, con su comentario. 82 | 83 | $ git add lib/HolaMundo.php 84 | $ git commit -m "Añadida la clase HolaMundo" 85 | [hola 6932156] Añadida la clase HolaMundo 86 | 1 file changed, 16 insertions(+) 87 | create mode 100644 lib/HolaMundo.php 88 | $ git add lib/hola.php 89 | $ git commit -m "hola usa la clase HolaMundo" 90 | [hola 9862f33] hola usa la clase HolaMundo 91 | 1 file changed, 3 insertions(+), 1 deletion(-) 92 | 93 | ```mermaid 94 | gitGraph: 95 | commit id: "e19f2c1" 96 | commit id: "efc252e" 97 | commit id: "3283e0d" tag: "v1-beta" 98 | commit id: "fd4da94" tag: "v1" 99 | commit id: "96a39df" 100 | commit id: "8c2a509" 101 | branch hola 102 | commit id: "6932156" 103 | commit id: "9862f33" 104 | ``` 105 | 106 | Y ahora con la orden `git checkout` podemos movernos entre ramas: 107 | 108 | $ git checkout main 109 | Switched to branch 'main' 110 | $ git checkout hola 111 | Switched to branch 'hola' 112 | 113 | ### Modificaciones en la rama main 114 | 115 | Podemos volver y añadir un nuevo archivo a la rama principal: 116 | 117 | $ git checkout main 118 | Switched to branch 'main' 119 | 120 | Creamos un archivo llamado `README.md` en la raíz de nuestro proyecto con el siguiente contenido: 121 | 122 | ```md 123 | # Curso de GIT 124 | 125 | Este proyecto contiene el curso de introducción a GIT 126 | ``` 127 | 128 | Y lo añadimos a nuestro repositorio en la rama en la que estamos: 129 | 130 | $ git add README.md 131 | $ git commit -m "Añadido README.md" 132 | [main c3e65d0] Añadido README.md 133 | 1 file changed, 3 insertions(+) 134 | create mode 100644 README.md 135 | $ git hist --all 136 | * c3e65d0 2013-06-16 | Añadido README.md (HEAD, main) [Sergio Gómez] 137 | | * 9862f33 2013-06-16 | hola usa la clase HolaMundo (hola) [Sergio Gómez] 138 | | * 6932156 2013-06-16 | Añadida la clase HolaMundo [Sergio Gómez] 139 | |/ 140 | * 81c6e93 2013-06-16 | Movido hola.php a lib [Sergio Gómez] 141 | * 96a39df 2013-06-16 | Añadido el autor del programa y su email [Sergio Gómez] 142 | * fd4da94 2013-06-16 | Se añade un comentario al cambio del valor por defecto (tag: v1) [Sergio Gómez] 143 | * 3283e0d 2013-06-16 | Se añade un parámetro por defecto (tag: v1-beta) [Sergio Gómez] 144 | * efc252e 2013-06-16 | Parametrización del programa [Sergio Gómez] 145 | * e19f2c1 2013-06-16 | Creación del proyecto [Sergio Gómez] 146 | 147 | Y vemos como `git hist` muestra la bifurcación en nuestro código. 148 | 149 | ```mermaid 150 | gitGraph: 151 | commit id: "e19f2c1" 152 | commit id: "efc252e" 153 | commit id: "3283e0d" tag: "v1-beta" 154 | commit id: "fd4da94" tag: "v1" 155 | commit id: "96a39df" 156 | commit id: "8c2a509" 157 | branch hola 158 | commit id: "6932156" 159 | commit id: "9862f33" 160 | checkout main 161 | commit id: "c3e65d0" 162 | ``` 163 | 164 | ## Fusión de ramas y resolución de conflictos 165 | 166 | ### Mezclar ramas 167 | 168 | Podemos incorporar los cambios de una rama a otra con la orden `git merge` 169 | 170 | $ git checkout hola 171 | Switched to branch 'hola' 172 | $ git merge main 173 | Merge made by the 'recursive' strategy. 174 | README.md | 3 +++ 175 | 1 file changed, 3 insertions(+) 176 | create mode 100644 README.md 177 | $ git hist --all 178 | * 9c6ac06 2013-06-16 | Merge commit 'c3e65d0' into hola (HEAD, hola) [Sergio Gómez] 179 | |\ 180 | * | 9862f33 2013-06-16 | hola usa la clase HolaMundo [Sergio Gómez] 181 | * | 6932156 2013-06-16 | Añadida la clase HolaMundo [Sergio Gómez] 182 | | | 183 | | * c3e65d0 2013-06-16 | Añadido README.md [Sergio Gómez] 184 | |/ 185 | * 81c6e93 2013-06-16 | Movido hola.php a lib [Sergio Gómez] 186 | * 96a39df 2013-06-16 | Añadido el autor del programa y su email [Sergio Gómez] 187 | * fd4da94 2013-06-16 | Se añade un comentario al cambio del valor por defecto (tag: v1) [Sergio Gómez] 188 | * 3283e0d 2013-06-16 | Se añade un parámetro por defecto (tag: v1-beta) [Sergio Gómez] 189 | * efc252e 2013-06-16 | Parametrización del programa [Sergio Gómez] 190 | * e19f2c1 2013-06-16 | Creación del proyecto [Sergio Gómez] 191 | 192 | ```mermaid 193 | gitGraph: 194 | commit id: "e19f2c1" 195 | commit id: "efc252e" 196 | commit id: "3283e0d" tag: "v1-beta" 197 | commit id: "fd4da94" tag: "v1" 198 | commit id: "96a39df" 199 | commit id: "8c2a509" 200 | branch hola 201 | commit id: "6932156" 202 | commit id: "9862f33" 203 | checkout main 204 | commit id: "c3e65d0" 205 | checkout hola 206 | merge main id: "9c6ac06" 207 | ``` 208 | 209 | De esa forma se puede trabajar en una rama secundaria incorporando los cambios de la rama principal o de otra rama. 210 | 211 | ### Resolver conflictos 212 | 213 | Un conflicto es cuando se produce una fusión que Git no es capaz de resolver. Vamos a modificar la rama main para crear uno con la rama hola. 214 | 215 | $ git checkout main 216 | Switched to branch 'main' 217 | 218 | Modificamos nuestro archivo _hola.php_ de nuevo: 219 | 220 | ```php 221 | 223 | print "Introduce tu nombre:"; 224 | $nombre = trim(fgets(STDIN)); 225 | @print "Hola, {$nombre}\n"; 226 | ``` 227 | 228 | Y guardamos los cambios: 229 | 230 | $ git add lib/hola.php 231 | $ git commit -m "Programa interactivo" 232 | [main 9c85275] Programa interactivo 233 | 1 file changed, 2 insertions(+), 2 deletions(-) 234 | $ git hist --all 235 | * 9c6ac06 2013-06-16 | Merge commit 'c3e65d0' into hola (hola) [Sergio Gómez] 236 | |\ 237 | * | 9862f33 2013-06-16 | hola usa la clase HolaMundo [Sergio Gómez] 238 | * | 6932156 2013-06-16 | Añadida la clase HolaMundo [Sergio Gómez] 239 | | | * 9c85275 2013-06-16 | Programa interactivo (HEAD, main) [Sergio Gómez] 240 | | |/ 241 | | * c3e65d0 2013-06-16 | Añadido README.md [Sergio Gómez] 242 | |/ 243 | * 81c6e93 2013-06-16 | Movido hola.php a lib [Sergio Gómez] 244 | * 96a39df 2013-06-16 | Añadido el autor del programa y su email [Sergio Gómez] 245 | * fd4da94 2013-06-16 | Se añade un comentario al cambio del valor por defecto (tag: v1) [Sergio Gómez] 246 | * 3283e0d 2013-06-16 | Se añade un parámetro por defecto (tag: v1-beta) [Sergio Gómez] 247 | * efc252e 2013-06-16 | Parametrización del programa [Sergio Gómez] 248 | * e19f2c1 2013-06-16 | Creación del proyecto [Sergio Gómez] 249 | 250 | ```mermaid 251 | gitGraph: 252 | commit id: "e19f2c1" 253 | commit id: "efc252e" 254 | commit id: "3283e0d" tag: "v1-beta" 255 | commit id: "fd4da94" tag: "v1" 256 | commit id: "96a39df" 257 | commit id: "8c2a509" 258 | branch hola 259 | commit id: "6932156" 260 | commit id: "9862f33" 261 | checkout main 262 | commit id: "c3e65d0" 263 | checkout hola 264 | merge main id: "9c6ac06" 265 | checkout main 266 | commit id: "9c85275" 267 | ``` 268 | 269 | Volvemos a la rama hola y fusionamos: 270 | 271 | $ git checkout hola 272 | Switched to branch 'hola' 273 | $ git merge main 274 | Auto-merging lib/hola.php 275 | CONFLICT (content): Merge conflict in lib/hola.php 276 | Automatic merge failed; fix conflicts and then commit the result. 277 | 278 | Si editamos nuestro archivo `lib/hola.php` obtendremos algo similar a esto: 279 | 280 | ```php 281 | 283 | <<<<<<< HEAD 284 | // El nombre por defecto es Mundo 285 | require('HolaMundo.php'); 286 | 287 | $nombre = isset($argv[1]) ? $argv[1] : "Mundo"; 288 | print new HolaMundo($nombre); 289 | ======= 290 | print "Introduce tu nombre:"; 291 | $nombre = trim(fgets(STDIN)); 292 | @print "Hola, {$nombre}\n"; 293 | >>>>>>> main 294 | ``` 295 | 296 | La primera parte marca el código que estaba en la rama donde trabajábamos (HEAD) y la parte final el código de donde fusionábamos. Resolvemos el conflicto, dejando el archivo como sigue: 297 | 298 | ```php 299 | 301 | require('HolaMundo.php'); 302 | 303 | print "Introduce tu nombre:"; 304 | $nombre = trim(fgets(STDIN)); 305 | print new HolaMundo($nombre); 306 | ``` 307 | 308 | Y resolvemos el conflicto confirmando los cambios: 309 | 310 | $ git add lib/hola.php 311 | $ git commit -m "Solucionado el conflicto al fusionar con la rama main" 312 | [hola a36af04] Solucionado el conflicto al fusionar con la rama main 313 | 314 | ```mermaid 315 | gitGraph: 316 | commit id: "e19f2c1" 317 | commit id: "efc252e" 318 | commit id: "3283e0d" tag: "v1-beta" 319 | commit id: "fd4da94" tag: "v1" 320 | commit id: "96a39df" 321 | commit id: "8c2a509" 322 | branch hola 323 | commit id: "6932156" 324 | commit id: "9862f33" 325 | checkout main 326 | commit id: "c3e65d0" 327 | checkout hola 328 | merge main id: "9c6ac06" 329 | checkout main 330 | commit id: "9c85275" 331 | checkout hola 332 | merge main id: "a36af04" 333 | ``` 334 | 335 | ### Rebasing vs Merging 336 | 337 | Rebasing es otra técnica para fusionar distinta a merge y usa la orden `git rebase`. Vamos a dejar nuestro proyecto como estaba antes del fusionado. Para ello necesitamos anotar el hash anterior al de la acción de _merge_. El que tiene la anotación _"hola usa la clase HolaMundo"_. 338 | 339 | Para ello podemos usar la orden `git reset` que nos permite mover HEAD donde queramos. 340 | 341 | $ git checkout hola 342 | Switched to branch 'hola' 343 | $ git hist 344 | * a36af04 2013-06-16 | Solucionado el conflicto al fusionar con la rama main (HEAD, hola) [Sergio Gómez] 345 | |\ 346 | | * 9c85275 2013-06-16 | Programa interactivo (main) [Sergio Gómez] 347 | * | 9c6ac06 2013-06-16 | Merge commit 'c3e65d0' into hola [Sergio Gómez] 348 | |\ \ 349 | | |/ 350 | | * c3e65d0 2013-06-16 | Añadido README.md [Sergio Gómez] 351 | * | 9862f33 2013-06-16 | hola usa la clase HolaMundo [Sergio Gómez] 352 | * | 6932156 2013-06-16 | Añadida la clase HolaMundo [Sergio Gómez] 353 | |/ 354 | * 81c6e93 2013-06-16 | Movido hola.php a lib [Sergio Gómez] 355 | * 96a39df 2013-06-16 | Añadido el autor del programa y su email [Sergio Gómez] 356 | * fd4da94 2013-06-16 | Se añade un comentario al cambio del valor por defecto (tag: v1) [Sergio Gómez] 357 | * 3283e0d 2013-06-16 | Se añade un parámetro por defecto (tag: v1-beta) [Sergio Gómez] 358 | * efc252e 2013-06-16 | Parametrización del programa [Sergio Gómez] 359 | * e19f2c1 2013-06-16 | Creación del proyecto [Sergio Gómez] 360 | $ git reset --hard 9862f33 361 | HEAD is now at 9862f33 hola usa la clase HolaMundo 362 | 363 | Y nuestro estado será: 364 | 365 | $ git hist --all 366 | * 9862f33 2013-06-16 | hola usa la clase HolaMundo (HEAD, hola) [Sergio Gómez] 367 | * 6932156 2013-06-16 | Añadida la clase HolaMundo [Sergio Gómez] 368 | | * 9c85275 2013-06-16 | Programa interactivo (main) [Sergio Gómez] 369 | | * c3e65d0 2013-06-16 | Añadido README.md [Sergio Gómez] 370 | |/ 371 | * 81c6e93 2013-06-16 | Movido hola.php a lib [Sergio Gómez] 372 | * 96a39df 2013-06-16 | Añadido el autor del programa y su email [Sergio Gómez] 373 | * fd4da94 2013-06-16 | Se añade un comentario al cambio del valor por defecto (tag: v1) [Sergio Gómez] 374 | * 3283e0d 2013-06-16 | Se añade un parámetro por defecto (tag: v1-beta) [Sergio Gómez] 375 | * efc252e 2013-06-16 | Parametrización del programa [Sergio Gómez] 376 | * e19f2c1 2013-06-16 | Creación del proyecto [Sergio Gómez] 377 | 378 | ```mermaid 379 | gitGraph: 380 | commit id: "e19f2c1" 381 | commit id: "efc252e" 382 | commit id: "3283e0d" tag: "v1-beta" 383 | commit id: "fd4da94" tag: "v1" 384 | commit id: "96a39df" 385 | commit id: "8c2a509" 386 | branch hola 387 | commit id: "6932156" 388 | commit id: "9862f33" 389 | checkout main 390 | commit id: "c3e65d0" 391 | commit id: "9c85275" 392 | ``` 393 | 394 | Hemos desecho todos los _merge_ y nuestro árbol está _"limpio"_. Vamos a probar ahora a hacer un rebase. Continuamos en la rama `hola` y ejecutamos lo siguiente: 395 | 396 | $ git rebase main 397 | First, rewinding head to replay your work on top of it... 398 | Applying: Añadida la clase HolaMundo 399 | Applying: hola usa la clase HolaMundo 400 | Using index info to reconstruct a base tree... 401 | M lib/hola.php 402 | Falling back to patching base and 3-way merge... 403 | Auto-merging lib/hola.php 404 | CONFLICT (content): Merge conflict in lib/hola.php 405 | error: Failed to merge in the changes. 406 | Patch failed at 0002 hola usa la clase HolaMundo 407 | The copy of the patch that failed is found in: .git/rebase-apply/patch 408 | 409 | When you have resolved this problem, run "git rebase --continue". 410 | If you prefer to skip this patch, run "git rebase --skip" instead. 411 | To check out the original branch and stop rebasing, run "git rebase --abort". 412 | 413 | El conflicto, por supuesto, se sigue dando. Resolvemos guardando el archivo `hola.php` como en los casos anteriores: 414 | 415 | ```php 416 | 418 | require('HolaMundo.php'); 419 | 420 | print "Introduce tu nombre:"; 421 | $nombre = trim(fgets(STDIN)); 422 | print new HolaMundo($nombre); 423 | ``` 424 | 425 | Añadimos los cambios en _staging_ y en esta ocasión, y tal como nos indicaba en el mensaje anterior, no tenemos que hacer `git commit` sino continuar con el _rebase_: 426 | 427 | $ git add lib/hola.php 428 | $ git status 429 | rebase in progress; onto 269eaca 430 | You are currently rebasing branch 'hola' on '269eaca'. 431 | (all conflicts fixed: run "git rebase --continue") 432 | 433 | Changes to be committed: 434 | (use "git reset HEAD ..." to unstage) 435 | 436 | modified: lib/hola.php 437 | $ git rebase --continue 438 | Applying: hola usa la clase HolaMundo 439 | 440 | Y ahora vemos que nuestro árbol tiene un aspecto distinto, mucho más limpio: 441 | 442 | $ git hist --all 443 | * 9862f33 2013-06-16 | hola usa la clase HolaMundo (HEAD -> hola) [Sergio Gómez] 444 | * 6932156 2013-06-16 | Añadida la clase HolaMundo [Sergio Gómez] 445 | * 9c85275 2013-06-16 | Programa interactivo (main) [Sergio Gómez] 446 | * c3e65d0 2013-06-16 | Añadido README.md [Sergio Gómez] 447 | * 81c6e93 2013-06-16 | Movido hola.php a lib [Sergio Gómez] 448 | * 96a39df 2013-06-16 | Añadido el autor del programa y su email [Sergio Gómez] 449 | * fd4da94 2013-06-16 | Se añade un comentario al cambio del valor por defecto (tag: v1) [Sergio Gómez] 450 | * 3283e0d 2013-06-16 | Se añade un parámetro por defecto (tag: v1-beta) [Sergio Gómez] 451 | * efc252e 2013-06-16 | Parametrización del programa [Sergio Gómez] 452 | * e19f2c1 2013-06-16 | Creación del proyecto [Sergio Gómez] 453 | 454 | ```mermaid 455 | gitGraph: 456 | commit id: "e19f2c1" 457 | commit id: "efc252e" 458 | commit id: "3283e0d" tag: "v1-beta" 459 | commit id: "fd4da94" tag: "v1" 460 | commit id: "96a39df" 461 | commit id: "8c2a509" 462 | commit id: "c3e65d0" 463 | commit id: "9c85275" 464 | branch hola 465 | commit id: "6932156" 466 | commit id: "9862f33" 467 | ``` 468 | 469 | 470 | Lo que hace rebase es volver a aplicar todos los cambios a la rama máster, desde su nodo más reciente. Eso significa que se modifica el orden o la historia de creación de los cambios. Por eso rebase no debe usarse si el orden es importante o si la rama es compartida. 471 | 472 | ## Mezclando con la rama main 473 | 474 | Ya hemos terminado de implementar los cambios en nuestra rama secundaria y es hora de llevar los cambios a la rama principal. Usamos `git merge` para hacer una fusión normal: 475 | 476 | $ git checkout main 477 | Switched to branch 'main' 478 | $ git merge hola 479 | Updating c3e65d0..491f1d2 480 | Fast-forward 481 | lib/HolaMundo.php | 16 ++++++++++++++++ 482 | lib/hola.php | 4 +++- 483 | 2 files changed, 19 insertions(+), 1 deletion(-) 484 | create mode 100644 lib/HolaMundo.php 485 | $ git hist --all 486 | * 9862f33 2013-06-16 | hola usa la clase HolaMundo (HEAD -> main, hola) [Sergio Gómez] 487 | * 6932156 2013-06-16 | Añadida la clase HolaMundo [Sergio Gómez] 488 | * 9c85275 2013-06-16 | Programa interactivo [Sergio Gómez] 489 | * c3e65d0 2013-06-16 | Añadido README.md [Sergio Gómez] 490 | * 81c6e93 2013-06-16 | Movido hola.php a lib [Sergio Gómez] 491 | * 96a39df 2013-06-16 | Añadido el autor del programa y su email [Sergio Gómez] 492 | * fd4da94 2013-06-16 | Se añade un comentario al cambio del valor por defecto (tag: v1) [Sergio Gómez] 493 | * 3283e0d 2013-06-16 | Se añade un parámetro por defecto (tag: v1-beta) [Sergio Gómez] 494 | * efc252e 2013-06-16 | Parametrización del programa [Sergio Gómez] 495 | * e19f2c1 2013-06-16 | Creación del proyecto [Sergio Gómez] 496 | 497 | 498 | Vemos que indica que el tipo de fusión es _fast-forward_. Este tipo de fusión tiene el problema que no deja rastro de la fusión, por eso suele ser recomendable usar el parámetro `--no-ff` para que quede constancia siempre de que se ha fusionado una rama con otra. 499 | 500 | Vamos a volver a probar ahora sin hacer _fast-forward_. Reseteamos _main_ al estado _"Programa interactivo"_. 501 | 502 | $ git reset --hard 9c85275 503 | $ git hist --all 504 | * 9862f33 2013-06-16 | hola usa la clase HolaMundo (HEAD -> hola) [Sergio Gómez] 505 | * 6932156 2013-06-16 | Añadida la clase HolaMundo [Sergio Gómez] 506 | * 9c85275 2013-06-16 | Programa interactivo (main) [Sergio Gómez] 507 | * c3e65d0 2013-06-16 | Añadido README.md [Sergio Gómez] 508 | * 81c6e93 2013-06-16 | Movido hola.php a lib [Sergio Gómez] 509 | * 96a39df 2013-06-16 | Añadido el autor del programa y su email [Sergio Gómez] 510 | * fd4da94 2013-06-16 | Se añade un comentario al cambio del valor por defecto (tag: v1) [Sergio Gómez] 511 | * 3283e0d 2013-06-16 | Se añade un parámetro por defecto (tag: v1-beta) [Sergio Gómez] 512 | * efc252e 2013-06-16 | Parametrización del programa [Sergio Gómez] 513 | * e19f2c1 2013-06-16 | Creación del proyecto [Sergio Gómez] 514 | 515 | Vemos que estamos como en el final de la sección anterior, así que ahora mezclamos: 516 | 517 | $ git merge -m "Aplicando los cambios de la rama hola" --no-ff hola 518 | Merge made by the 'recursive' strategy. 519 | lib/HolaMundo.php | 16 ++++++++++++++++ 520 | lib/hola.php | 4 +++- 521 | 2 files changed, 19 insertions(+), 1 deletion(-) 522 | create mode 100644 lib/HolaMundo.php 523 | $ git hist --all 524 | * 2eab8ca 2013-06-16 | Aplicando los cambios de la rama hola (HEAD -> main) [Sergio Gomez] 525 | *\ 526 | | * 9862f33 2013-06-16 | hola usa la clase HolaMundo (hola) [Sergio Gómez] 527 | | * 6932156 2013-06-16 | Añadida la clase HolaMundo [Sergio Gómez] 528 | |/ 529 | * 9c85275 2013-06-16 | Programa interactivo (main) [Sergio Gómez] 530 | * c3e65d0 2013-06-16 | Añadido README.md [Sergio Gómez] 531 | * 81c6e93 2013-06-16 | Movido hola.php a lib [Sergio Gómez] 532 | * 96a39df 2013-06-16 | Añadido el autor del programa y su email [Sergio Gómez] 533 | * fd4da94 2013-06-16 | Se añade un comentario al cambio del valor por defecto (tag: v1) [Sergio Gómez] 534 | * 3283e0d 2013-06-16 | Se añade un parámetro por defecto (tag: v1-beta) [Sergio Gómez] 535 | * efc252e 2013-06-16 | Parametrización del programa [Sergio Gómez] 536 | * e19f2c1 2013-06-16 | Creación del proyecto [Sergio Gómez] 537 | 538 | ```mermaid 539 | gitGraph: 540 | commit id: "e19f2c1" 541 | commit id: "efc252e" 542 | commit id: "3283e0d" tag: "v1-beta" 543 | commit id: "fd4da94" tag: "v1" 544 | commit id: "96a39df" 545 | commit id: "8c2a509" 546 | commit id: "c3e65d0" 547 | commit id: "9c85275" 548 | branch hola 549 | commit id: "6932156" 550 | commit id: "9862f33" 551 | checkout main 552 | merge hola id: "2eab8ca" 553 | ``` 554 | 555 | 556 | En la siguiente imagen se puede ver la diferencia: 557 | 558 | ![Diferencias entre tipos de fusión](images/gitlab-merge-ff.png) 559 | -------------------------------------------------------------------------------- /docs/referencias.md: -------------------------------------------------------------------------------- 1 | # Referencias 2 | 3 | - [Documentación oficial en inglés](http://git-scm.com/documentation). 4 | - [Documentación oficial en español (quizás incompleta)](http://git-scm.com/book/es). 5 | - [Curso de Git (inglés)](http://gitimmersion.com/lab_01.html). La mayoría de la documentación de este manual está basada en este curso. 6 | - [Curso interactivo de Git (inglés)](http://try.github.io/levels/1/challenges/1). 7 | - [Página de referencia de todas las órdenes de Git (inglés)](http://gitref.org/). 8 | - [Chuleta con las órdenes más usuales de Git](http://byte.kde.org/~zrusin/git/git-cheat-sheet-large.png). 9 | - [Gitmagic (ingles y español). Otro manual de Git](http://www-cs-students.stanford.edu/~blynn/gitmagic/intl/es/) 10 | - [Artículo técnico: Un modelo exitoso de ramificación en Git ](http://nvie.com/posts/a-successful-git-branching-model/). 11 | - [Curso detallado y gratuito sobre Git y github](https://www.udacity.com/course/how-to-use-git-and-github--ud775) 12 | - [Otra guia rápida de git](https://github.com/github/training-kit/blob/main/downloads/github-git-cheat-sheet.pdf) 13 | - [Guía de estilos según Udacity](http://udacity.github.io/git-styleguide/) 14 | - [Flujo de trabajo de Gitflow](https://www.atlassian.com/es/git/tutorials/comparing-workflows/gitflow-workflow) 15 | -------------------------------------------------------------------------------- /docs/stylesheets/extra.css: -------------------------------------------------------------------------------- 1 | img[alt$=">"] { 2 | float: right; 3 | } 4 | 5 | img[alt$="<"] { 6 | float: left; 7 | } 8 | 9 | img { 10 | display: block; 11 | max-width: 100%; 12 | height: auto; 13 | margin: auto; 14 | float: none !important; 15 | } 16 | 17 | :root { 18 | --md-primary-fg-color: #60102f; 19 | --md-primary-fg-color--light: rgb(123, 136, 204); 20 | --md-primary-fg-color--dark: #34091a; 21 | } 22 | -------------------------------------------------------------------------------- /docs/usoavanzado.md: -------------------------------------------------------------------------------- 1 | # Uso avanzado de Git 2 | 3 | ## Deshacer cambios 4 | 5 | ### Deshaciendo cambios antes de la fase de staging. 6 | 7 | Volvemos a la rama máster y vamos a modificar el comentario que pusimos: 8 | 9 | $ git checkout main 10 | Previous HEAD position was 3283e0d... Se añade un parámetro por defecto 11 | Switched to branch 'main' 12 | 13 | Modificamos _hola.php_ de la siguiente manera: 14 | 15 | ```php 16 | ..." to update what will be committed) 28 | # (use "git checkout -- ..." to discard changes in working directory) 29 | # 30 | # modified: hola.php 31 | # 32 | no changes added to commit (use "git add" and/or "git commit -a") 33 | 34 | El mismo Git nos indica que debemos hacer para añadir los cambios o para deshacerlos: 35 | 36 | $ git checkout hola.php 37 | $ git status 38 | # On branch main 39 | nothing to commit, working directory clean 40 | $ cat hola.php 41 | ..." to unstage) 65 | # 66 | # modified: hola.php 67 | # 68 | 69 | De nuevo, Git nos indica qué debemos hacer para deshacer el cambio: 70 | 71 | $ git reset HEAD hola.php 72 | Unstaged changes after reset: 73 | M hola.php 74 | $ git status 75 | # On branch main 76 | # Changes not staged for commit: 77 | # (use "git add ..." to update what will be committed) 78 | # (use "git checkout -- ..." to discard changes in working directory) 79 | # 80 | # modified: hola.php 81 | # 82 | no changes added to commit (use "git add" and/or "git commit -a") 83 | $ git checkout hola.php 84 | 85 | Y ya tenemos nuestro repositorio limpio otra vez. Como vemos hay que hacerlo en dos pasos: 86 | uno para borrar los datos del _staging_ y otro para restaurar la copia de trabajo. 87 | 88 | ### Deshaciendo commits no deseados. 89 | 90 | Si a pesar de todo hemos hecho un commit y nos hemos equivocado, podemos deshacerlo con la orden `git revert`. 91 | Modificamos otra vez el archivo como antes: 92 | 93 | ```php 94 | 197 | // El nombre por defecto es Mundo 198 | $nombre = isset($argv[1]) ? $argv[1] : "Mundo"; 199 | @print "Hola, {$nombre}\n"; 200 | ``` 201 | 202 | Y en esta ocasión usamos `commit --amend` que nos permite modificar el último estado confirmado, sustituyéndolo por el estado actual: 203 | 204 | $ git add hola.php 205 | $ git commit --amend -m "Añadido el autor del programa y su email" 206 | [main 96a39df] Añadido el autor del programa y su email 207 | 1 file changed, 1 insertion(+) 208 | $ git hist 209 | * 96a39df 2013-06-16 | Añadido el autor del programa y su email (HEAD, main) [Sergio Gómez] 210 | * fd4da94 2013-06-16 | Se añade un comentario al cambio del valor por defecto (tag: v1) [Sergio Gómez] 211 | * 3283e0d 2013-06-16 | Se añade un parámetro por defecto (tag: v1-beta) [Sergio Gómez] 212 | * efc252e 2013-06-16 | Parametrización del programa [Sergio Gómez] 213 | * e19f2c1 2013-06-16 | Creación del proyecto [Sergio Gómez] 214 | 215 | ```mermaid 216 | gitGraph: 217 | commit id: "e19f2c1" 218 | commit id: "efc252e" 219 | commit id: "3283e0d" tag: "v1-beta" 220 | commit id: "fd4da94" tag: "v1" 221 | commit id: "96a39df" 222 | ``` 223 | 224 | !!! danger 225 | 226 | Nunca modifiques un _commit_ que ya hayas sincronizado con otro repositorio o 227 | que hayas recibido de él. Estarías alterando la historia de cambios y provocarías 228 | problemas de sincronización. 229 | 230 | ## Moviendo y borrando archivos 231 | 232 | ### Mover un archivo a otro directorio con git 233 | 234 | Para mover archivos usaremos la orden `git mv`: 235 | 236 | $ mkdir lib 237 | $ git mv hola.php lib 238 | $ git status 239 | # On branch main 240 | # Changes to be committed: 241 | # (use "git reset HEAD ..." to unstage) 242 | # 243 | # renamed: hola.php -> lib/hola.php 244 | # 245 | 246 | ### Mover y borrar archivos. 247 | 248 | Podíamos haber hecho el paso anterior con la órden del sistema _mv_ y el resultado hubiera sido el mismo. Lo siguiente es a modo de ejemplo y no es necesario que lo ejecutes: 249 | 250 | $ mkdir lib 251 | $ mv hola.php lib 252 | $ git add lib/hola.php 253 | $ git rm hola.php 254 | 255 | Y, ahora sí, ya podemos guardar los cambios: 256 | 257 | $ git commit -m "Movido hola.php a lib." 258 | [main 8c2a509] Movido hola.php a lib. 259 | 1 file changed, 0 insertions(+), 0 deletions(-) 260 | rename hola.php => lib/hola.php (100%) 261 | 262 | 263 | ```mermaid 264 | gitGraph: 265 | commit id: "e19f2c1" 266 | commit id: "efc252e" 267 | commit id: "3283e0d" tag: "v1-beta" 268 | commit id: "fd4da94" tag: "v1" 269 | commit id: "96a39df" 270 | commit id: "8c2a509" 271 | ``` -------------------------------------------------------------------------------- /docs/usobasico.md: -------------------------------------------------------------------------------- 1 | # Uso básico de Git 2 | 3 | ## Crear un proyecto 4 | 5 | ### Crear un programa "Hola Mundo" 6 | 7 | Creamos un directorio donde colocar el código 8 | 9 | $ mkdir curso-de-git 10 | $ cd curso-de-git 11 | 12 | Creamos un fichero `hola.php` que muestre Hola Mundo. 13 | 14 | ```php 15 | ..." to update what will be committed) 62 | # (use "git checkout -- ..." to discard changes in working directory) 63 | # 64 | # modified: hola.php 65 | # 66 | no changes added to commit (use "git add" and/or "git commit -a") 67 | 68 | ### Añadir cambios 69 | 70 | Con la orden `git add` indicamos a git que prepare los cambios para que sean almacenados. 71 | 72 | $ git add hola.php 73 | $ git status 74 | # On branch main 75 | # Changes to be committed: 76 | # (use "git reset HEAD ..." to unstage) 77 | # 78 | # modified: hola.php 79 | # 80 | 81 | ### Confirmar los cambios 82 | 83 | Con la orden `git commit` confirmamos los cambios definitivamente, lo que hace que se guarden permanentemente en nuestro repositorio. 84 | 85 | $ git commit -m "Parametrización del programa" 86 | [main efc252e] Parametrización del programa 87 | 1 file changed, 1 insertion(+), 1 deletion(-) 88 | $ git status 89 | # On branch main 90 | nothing to commit (working directory clean) 91 | 92 | ```mermaid 93 | gitGraph: 94 | commit id: "e19f2c1" 95 | commit id: "efc252e" 96 | ``` 97 | 98 | ### Diferencias entre _workdir_ y _staging_. 99 | 100 | Modificamos nuestra aplicación para que soporte un parámetro por defecto y añadimos los cambios. 101 | 102 | ```php 103 | ..." to unstage) 127 | # 128 | # modified: hola.php 129 | # 130 | # Changes not staged for commit: 131 | # (use "git add ..." to update what will be committed) 132 | # (use "git checkout -- ..." to discard changes in working directory) 133 | # 134 | # modified: hola.php 135 | # 136 | 137 | Podemos ver como aparecen el archivo _hola.php_ dos veces. El primero está preparado 138 | para ser confirmado y está almacenado en la zona de _staging_. El segundo indica 139 | que el directorio hola.php está modificado otra vez en la zona de trabajo (_workdir_). 140 | 141 | !!! warning 142 | 143 | Si volvieramos a hacer un `git add hola.php` sobreescribiríamos los cambios previos 144 | que había en la zona de _staging_. 145 | 146 | Almacenamos los cambios por separado: 147 | 148 | $ git commit -m "Se añade un parámetro por defecto" 149 | [main 3283e0d] Se añade un parámetro por defecto 150 | 1 file changed, 2 insertions(+), 1 deletion(-) 151 | $ git status 152 | # On branch main 153 | # Changes not staged for commit: 154 | # (use "git add ..." to update what will be committed) 155 | # (use "git checkout -- ..." to discard changes in working directory) 156 | # 157 | # modified: hola.php 158 | # 159 | no changes added to commit (use "git add" and/or "git commit -a") 160 | $ git add . 161 | $ git status 162 | # On branch main 163 | # Changes to be committed: 164 | # (use "git reset HEAD ..." to unstage) 165 | # 166 | # modified: hola.php 167 | # 168 | $ git commit -m "Se añade un comentario al cambio del valor por defecto" 169 | [main fd4da94] Se añade un comentario al cambio del valor por defecto 170 | 1 file changed, 1 insertion(+) 171 | 172 | ```mermaid 173 | gitGraph: 174 | commit id: "e19f2c1" 175 | commit id: "efc252e" 176 | commit id: "3283e0d" 177 | commit id: "fd4da94" 178 | ``` 179 | !!! info 180 | 181 | El valor "." despues de `git add` indica que se añadan todos los archivos de forma recursiva. 182 | 183 | !!! warning 184 | 185 | Cuidado cuando uses `git add .` asegúrate de que no estás añadiendo archivos que no quieres añadir. 186 | 187 | ### Ignorando archivos 188 | 189 | La orden `git add .` o `git add nombre_directorio` es muy cómoda, ya que nos permite añadir todos los archivos del proyecto o todos los contenidos en un directorio y sus subdirectorios. Es mucho más rápido que tener que ir añadiéndolos uno por uno. El problema es que, si no se tiene cuidado, se puede terminar por añadir archivos innecesarios o con información sensible. 190 | 191 | Por lo general se debe evitar añadir archivos que se hayan generado como producto de la compilación del proyecto, los que generen los entornos de desarrollo (archivos de configuración y temporales) y aquellos que contentan información sensible, como contraseñas o tokens de autenticación. Por ejemplo, en un proyecto de `C/C++`, los archivos objeto no deben incluirse, solo los que contengan código fuente y los make que los generen. 192 | 193 | Para indicarle a _git_ que debe ignorar un archivo, se puede crear un fichero llamado _.gitignore_, bien en la raíz del proyecto o en los subdirectorios que queramos. Dicho fichero puede contener patrones, uno en cada línea, que especiquen qué archivos deben ignorarse. El formato es el siguiente: 194 | 195 | ``` 196 | # .gitignore 197 | dir1/ # ignora todo lo que contenga el directorio dir1 198 | !dir1/info.txt # El operador ! excluye del ignore a dir1/info.txt (sí se guardaría) 199 | dir2/*.txt # ignora todos los archivos txt que hay en el directorio dir2 200 | dir3/**/*.txt # ignora todos los archivos txt que hay en el dir3 y sus subdirectorios 201 | *.o # ignora todos los archivos con extensión .o en todos los directorios 202 | ``` 203 | 204 | Cada tipo de proyecto genera sus ficheros temporales, así que para cada proyecto hay un `.gitignore` apropiado. Existen repositorios que ya tienen creadas plantillas. Podéis encontrar uno en [https://github.com/github/gitignore](https://github.com/github/gitignore) 205 | 206 | ### Ignorando archivos globalmente 207 | 208 | Si bien, los archivos que hemos metido en `.gitignore`, deben ser aquellos ficheros temporales o de configuración que se pueden crear durante las fases de compilación o ejecución del programa, en ocasiones habrá otros ficheros que tampoco debemos introducir en el repositorio y que son recurrentes en todos los proyectos. En dicho caso, es más útil tener un _gitignore_ que sea global a todos nuestros proyectos. Esta configuración sería complementaria a la que ya tenemos. Ejemplos de lo que se puede ignorar de forma global son los ficheros temporales del sistema operativo (`*~`, `.nfs*`) y los que generan los entornos de desarrollo. 209 | 210 | Para indicar a _git_ que queremos tener un fichero de _gitignore_ global, tenemos que configurarlo con la siguiente orden: 211 | 212 | ``` 213 | git config --global core.excludesfile $HOME/.gitignore_global 214 | ``` 215 | 216 | Ahora podemos crear un archivo llamado `.gitignore_global` en la raíz de nuestra cuenta con este contenido: 217 | 218 | ``` 219 | # Compiled source # 220 | ################### 221 | *.com 222 | *.class 223 | *.dll 224 | *.exe 225 | *.o 226 | *.so 227 | 228 | # Packages # 229 | ############ 230 | # it's better to unpack these files and commit the raw source 231 | # git has its own built in compression methods 232 | *.7z 233 | *.dmg 234 | *.gz 235 | *.iso 236 | *.jar 237 | *.rar 238 | *.tar 239 | *.zip 240 | 241 | # Logs and databases # 242 | ###################### 243 | *.log 244 | *.sql 245 | *.sqlite 246 | 247 | # OS generated files # 248 | ###################### 249 | .DS_Store 250 | .DS_Store? 251 | ._* 252 | .Spotlight-V100 253 | .Trashes 254 | ehthumbs.db 255 | Thumbs.db 256 | *~ 257 | *.swp 258 | 259 | # IDEs # 260 | ###################### 261 | .idea 262 | .settings/ 263 | .classpath 264 | .project 265 | ``` 266 | 267 | ## Trabajando con el historial 268 | 269 | ### Observando los cambios 270 | 271 | Con la orden `git log` podemos ver todos los cambios que hemos hecho: 272 | 273 | $ git log 274 | commit fd4da946326fbe8b24e89282ad25a71721bf40f6 275 | Author: Sergio Gómez 276 | Date: Sun Jun 16 12:51:01 2013 +0200 277 | 278 | Se añade un comentario al cambio del valor por defecto 279 | 280 | commit 3283e0d306c8d42d55ffcb64e456f10510df8177 281 | Author: Sergio Gómez 282 | Date: Sun Jun 16 12:50:00 2013 +0200 283 | 284 | Se añade un parámetro por defecto 285 | 286 | commit efc252e11939351505a426a6e1aa5bb7dc1dd7c0 287 | Author: Sergio Gómez 288 | Date: Sun Jun 16 12:13:26 2013 +0200 289 | 290 | Parametrización del programa 291 | 292 | commit e19f2c1701069d9d1159e9ee21acaa1bbc47d264 293 | Author: Sergio Gómez 294 | Date: Sun Jun 16 11:55:23 2013 +0200 295 | 296 | Creación del proyecto 297 | 298 | También es posible ver versiones abreviadas o limitadas, dependiendo de los parámetros: 299 | 300 | $ git log --oneline 301 | fd4da94 Se añade un comentario al cambio del valor por defecto 302 | 3283e0d Se añade un parámetro por defecto 303 | efc252e Parametrización del programa 304 | e19f2c1 Creación del proyecto 305 | git log --oneline --max-count=2 306 | git log --oneline --since='5 minutes ago' 307 | git log --oneline --until='5 minutes ago' 308 | git log --oneline --author=sergio 309 | git log --oneline --all 310 | 311 | Una versión muy útil de `git log` es la siguiente, pues nos permite ver en que lugares está main y HEAD, entre otras cosas: 312 | 313 | $ git log --pretty=format:'%h %ad | %s%d [%an]' --graph --date=short 314 | * fd4da94 2013-06-16 | Se añade un comentario al cambio del valor por defecto (HEAD, main) [Sergio Gómez] 315 | * 3283e0d 2013-06-16 | Se añade un parámetro por defecto [Sergio Gómez] 316 | * efc252e 2013-06-16 | Parametrización del programa [Sergio Gómez] 317 | * e19f2c1 2013-06-16 | Creación del proyecto [Sergio Gómez] 318 | 319 | ### Crear alias 320 | 321 | Como estas órdenes son demasiado largas, Git nos permite crear alias para crear nuevas órdenes parametrizadas. Para ello podemos configurar nuestro entorno con la orden `git config` de la siguiente manera: 322 | 323 | git config --global alias.hist "log --pretty=format:'%h %ad | %s%d [%an]' --graph --date=short" 324 | 325 | !!! example 326 | 327 | Puedes configurar incluso alias para abreviar comandos. Algunos ejemplos de alias útiles: 328 | 329 | git config --global alias.br branch 330 | git config --global alias.co checkout 331 | git config --global alias.ci commit 332 | git config --global alias.st "status -u" 333 | git config --global alias.cane "commit --amend --no-edit" 334 | 335 | ### Recuperando versiones anteriores 336 | 337 | Cada cambio es etiquetado por un hash, para poder regresar a ese momento del estado del proyecto se usa la orden `git checkout`. 338 | 339 | $ git checkout e19f2c1 340 | Note: checking out 'e19f2c1'. 341 | 342 | You are in 'detached HEAD' state. You can look around, make experimental 343 | changes and commit them, and you can discard any commits you make in this 344 | state without impacting any branches by performing another checkout. 345 | 346 | If you want to create a new branch to retain commits you create, you may 347 | do so (now or later) by using -b with the checkout command again. Example: 348 | 349 | git checkout -b new_branch_name 350 | 351 | HEAD is now at e19f2c1... Creación del proyecto 352 | $ cat hola.php 353 | " 5 | site_description: "Curso básico de git" 6 | 7 | # Repository information 8 | repo_name: "aulasoftwarelibre/taller-de-git" 9 | repo_url: "https://github.com/aulasoftwarelibre/taller-de-git.git" 10 | 11 | # License 12 | copyright: Copyleft - CC BY-NC 4.0 - Aula de Software Libre 13 | 14 | # Configuration 15 | theme: 16 | favicon: "images/logoasl.png" 17 | features: 18 | - content.action.edit 19 | - content.action.view 20 | - content.code.annotate 21 | - content.code.copy 22 | - navigation.instant 23 | - navigation.footer 24 | - navigation.tracking 25 | icon: 26 | logo: material/git 27 | name: "material" 28 | language: "es" 29 | palette: 30 | # Palette toggle for automatic mode 31 | - media: "(prefers-color-scheme)" 32 | toggle: 33 | icon: material/link 34 | name: Switch to light mode 35 | - media: "(prefers-color-scheme: light)" 36 | scheme: default 37 | toggle: 38 | icon: material/toggle-switch-off-outline 39 | name: Switch to dark mode 40 | - media: "(prefers-color-scheme: dark)" 41 | scheme: slate 42 | toggle: 43 | icon: material/toggle-switch 44 | name: Switch to system preference 45 | 46 | extra: 47 | social: 48 | - icon: fontawesome/brands/github 49 | link: "https://github.com/aulasoftwarelibre" 50 | - icon: fontawesome/brands/twitter 51 | link: "https://twitter.com/aulasl" 52 | - icon: fontawesome/brands/facebook 53 | link: "https://facebook.com/aulasl" 54 | - icon: fontawesome/brands/instagram 55 | link: "https://instagram.com/aulasoftwarelibre" 56 | - icon: fontawesome/brands/youtube 57 | link: "https://www.youtube.com/c/AulaSoftwareLibre" 58 | - icon: fontawesome/brands/linkedin 59 | link: "https://www.linkedin.com/company/aulasoftwarelibre/" 60 | analytics: 61 | provider: google 62 | property: UA-51754922-1 63 | 64 | extra_css: 65 | - stylesheets/extra.css 66 | 67 | plugins: 68 | - search 69 | - social 70 | - git-revision-date-localized: 71 | type: date 72 | 73 | markdown_extensions: 74 | - abbr 75 | - admonition 76 | - attr_list 77 | - def_list 78 | - footnotes 79 | - md_in_html 80 | - pymdownx.arithmatex: 81 | generic: true 82 | - pymdownx.betterem: 83 | smart_enable: all 84 | - pymdownx.caret 85 | - pymdownx.details 86 | - pymdownx.emoji: 87 | emoji_generator: !!python/name:material.extensions.emoji.to_svg 88 | emoji_index: !!python/name:material.extensions.emoji.twemoji 89 | - pymdownx.highlight: 90 | anchor_linenums: true 91 | line_spans: __span 92 | pygments_lang_class: true 93 | - pymdownx.inlinehilite 94 | - pymdownx.keys 95 | - pymdownx.magiclink: 96 | normalize_issue_symbols: true 97 | repo_url_shorthand: true 98 | user: squidfunk 99 | repo: mkdocs-material 100 | - pymdownx.mark 101 | - pymdownx.smartsymbols 102 | - pymdownx.snippets: 103 | auto_append: 104 | - includes/mkdocs.md 105 | - pymdownx.superfences: 106 | custom_fences: 107 | - name: mermaid 108 | class: mermaid 109 | format: !!python/name:pymdownx.superfences.fence_code_format 110 | - pymdownx.tasklist: 111 | custom_checkbox: true 112 | - pymdownx.tilde 113 | - tables 114 | - toc: 115 | permalink: true 116 | 117 | # Page tree 118 | nav: 119 | - Inicio: index.md 120 | - Sistemas de control de versiones: cvs.md 121 | - Introducción a git: introduccion.md 122 | - Aspectos básicos de Git: git.md 123 | - Uso básico de Git: usobasico.md 124 | - Uso avanzado de Git: usoavanzado.md 125 | - Ramas: ramas.md 126 | - Github: github.md 127 | - Citar proyectos en GitHub: github-zenodo.md 128 | - Flujo de trabajo en GitHub: github-flow.md 129 | - Github avanzado: github-avanzado.md 130 | - Comandos de git: commands.md 131 | - Flujo de trabajo con Git: gitflow.md 132 | - Referencias: referencias.md 133 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "plantilla-talleres" 3 | version = "1.0.0" 4 | description = "Plantilla de talleres" 5 | authors = ["Aula de Software Libre "] 6 | license = "CC BY-NC 4.0" 7 | 8 | [tool.poetry.dependencies] 9 | python = "^3.9" 10 | 11 | [tool.poetry.group.dev.dependencies] 12 | Markdown = "^3.3.6" 13 | mkdocs = "^1.2.3" 14 | mkdocs-git-revision-date-localized-plugin = "^1.2.0" 15 | mkdocs-material = {extras = ["imaging"], version = "^9.5.4"} 16 | mkdocs-material-extensions = "^1.2" 17 | mkdocs-pandoc = "^0.2.6" 18 | pymdown-extensions = "^10.3" 19 | 20 | [build-system] 21 | requires = ["poetry-core>=1.0.0"] 22 | build-backend = "poetry.core.masonry.api" 23 | --------------------------------------------------------------------------------