[
  {
    "path": ".gitignore",
    "content": "node_modules/\r\npackage-lock.json\r\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: ruby\nrvm:\n  - 2.2\nbefore_script:\n  - gem install awesome_bot\n  - npm install\nscript:\n- awesome_bot README.md --allow-dupe --allow-redirect --allow-ssl\n- awesome_bot README_*.md --allow-dupe --allow-redirect --allow-ssl\n- npm run toc\n- npm run diff\n"
  },
  {
    "path": "CONTRIBUTE.md",
    "content": "# Contributing\n\nThis is a community built document. Dive in and help out!\n\n### Issues\n\n- Please jump in and help us out by making PRs for open issues.\n- If you see anything you'd think could be improved, feel free to open an issue. This doesn't just mean for new additions you'd like to see - although those are very appreciated, too.\n\n### Pull Requests\n\n- Please title your pull requests appropriately, summing up what your commits are about.\n- Make sure that your submission doesn't exist somewhere else in the document.\n- If you can, run `doctoc README.md` before adding a new section, or after editing a section - this keeps the Table of Contents up to date. If you don't have it, you can install [DocToc here](https://github.com/thlorenz/doctoc).\n- Include the relevant branch before the `$` in a shell command, if needed. If not needed, please do not include a branch name.\n- Please label code blocks as `sh` to help out [linguist](https://github.com/github/linguist), unless the language is different.\n- Try and put relevant flight rules in the same general area of the document - deletes with deletes, commit amends with commit amends, and so on. We're working on making this better, so no worries if it is confusing - just throw the submission on the end.\n- Link to places you found answers or procedures if especially complicated, or if linking to a larger discussion of how to do something. This normally means linking to Stack Overflow.\n- Generally, conform to this schema:\n\n        <a name=\"example-title\"></a>\n        # Example Title\n\n        Brief description of the problem.\n\n        ```sh\n        (relevant branch)$ git blah blah\n        ```\n\n## Translation\n\nWe use a translation tool called [GitLocalize][gl]. Please follow these steps to get started with your contributions:\n\n1. Go to [GitLocalize's k88hudson/git-flight-rules repository][gl-repo].\n1. Sign up using your GitHub account :octocat:.\n1. Find the document you are going to translate.\n1. Happy translating :sparkles: .\n1. When you are done, send the translation for reviews.\n1. The reviewed translation will be sent as a Pull Request to GitHub by the language moderator in the community.\n\nTo learn more about how GitLocalize works, visit their [help page][gl-help]. If you find any issues or feature requests, please file them in [GitLocalize's issue tracker][gl-issue-tracker].\n\n[gl]: https://gitlocalize.com\n[gl-help]: https://docs.gitlocalize.com/\n[gl-issue-tracker]: https://github.com/gitlocalize/feedback\n[gl-repo]: https://gitlocalize.com/repo/598\n"
  },
  {
    "path": "LICENSE",
    "content": "Attribution-ShareAlike 4.0 International\n\n=======================================================================\n\nCreative Commons Corporation (\"Creative Commons\") is not a law firm and\ndoes not provide legal services or legal advice. Distribution of\nCreative Commons public licenses does not create a lawyer-client or\nother relationship. Creative Commons makes its licenses and related\ninformation available on an \"as-is\" basis. Creative Commons gives no\nwarranties regarding its licenses, any material licensed under their\nterms and conditions, or any related information. Creative Commons\ndisclaims all liability for damages resulting from their use to the\nfullest extent possible.\n\nUsing Creative Commons Public Licenses\n\nCreative Commons public licenses provide a standard set of terms and\nconditions that creators and other rights holders may use to share\noriginal works of authorship and other material subject to copyright\nand certain other rights specified in the public license below. The\nfollowing considerations are for informational purposes only, are not\nexhaustive, and do not form part of our licenses.\n\n     Considerations for licensors: Our public licenses are\n     intended for use by those authorized to give the public\n     permission to use material in ways otherwise restricted by\n     copyright and certain other rights. Our licenses are\n     irrevocable. Licensors should read and understand the terms\n     and conditions of the license they choose before applying it.\n     Licensors should also secure all rights necessary before\n     applying our licenses so that the public can reuse the\n     material as expected. Licensors should clearly mark any\n     material not subject to the license. This includes other CC-\n     licensed material, or material used under an exception or\n     limitation to copyright. More considerations for licensors:\n\twiki.creativecommons.org/Considerations_for_licensors\n\n     Considerations for the public: By using one of our public\n     licenses, a licensor grants the public permission to use the\n     licensed material under specified terms and conditions. If\n     the licensor's permission is not necessary for any reason--for\n     example, because of any applicable exception or limitation to\n     copyright--then that use is not regulated by the license. Our\n     licenses grant only permissions under copyright and certain\n     other rights that a licensor has authority to grant. Use of\n     the licensed material may still be restricted for other\n     reasons, including because others have copyright or other\n     rights in the material. A licensor may make special requests,\n     such as asking that all changes be marked or described.\n     Although not required by our licenses, you are encouraged to\n     respect those requests where reasonable. More_considerations\n     for the public:\n\twiki.creativecommons.org/Considerations_for_licensees\n\n=======================================================================\n\nCreative Commons Attribution-ShareAlike 4.0 International Public\nLicense\n\nBy exercising the Licensed Rights (defined below), You accept and agree\nto be bound by the terms and conditions of this Creative Commons\nAttribution-ShareAlike 4.0 International Public License (\"Public\nLicense\"). To the extent this Public License may be interpreted as a\ncontract, You are granted the Licensed Rights in consideration of Your\nacceptance of these terms and conditions, and the Licensor grants You\nsuch rights in consideration of benefits the Licensor receives from\nmaking the Licensed Material available under these terms and\nconditions.\n\n\nSection 1 -- Definitions.\n\n  a. Adapted Material means material subject to Copyright and Similar\n     Rights that is derived from or based upon the Licensed Material\n     and in which the Licensed Material is translated, altered,\n     arranged, transformed, or otherwise modified in a manner requiring\n     permission under the Copyright and Similar Rights held by the\n     Licensor. For purposes of this Public License, where the Licensed\n     Material is a musical work, performance, or sound recording,\n     Adapted Material is always produced where the Licensed Material is\n     synched in timed relation with a moving image.\n\n  b. Adapter's License means the license You apply to Your Copyright\n     and Similar Rights in Your contributions to Adapted Material in\n     accordance with the terms and conditions of this Public License.\n\n  c. BY-SA Compatible License means a license listed at\n     creativecommons.org/compatiblelicenses, approved by Creative\n     Commons as essentially the equivalent of this Public License.\n\n  d. Copyright and Similar Rights means copyright and/or similar rights\n     closely related to copyright including, without limitation,\n     performance, broadcast, sound recording, and Sui Generis Database\n     Rights, without regard to how the rights are labeled or\n     categorized. For purposes of this Public License, the rights\n     specified in Section 2(b)(1)-(2) are not Copyright and Similar\n     Rights.\n\n  e. Effective Technological Measures means those measures that, in the\n     absence of proper authority, may not be circumvented under laws\n     fulfilling obligations under Article 11 of the WIPO Copyright\n     Treaty adopted on December 20, 1996, and/or similar international\n     agreements.\n\n  f. Exceptions and Limitations means fair use, fair dealing, and/or\n     any other exception or limitation to Copyright and Similar Rights\n     that applies to Your use of the Licensed Material.\n\n  g. License Elements means the license attributes listed in the name\n     of a Creative Commons Public License. The License Elements of this\n     Public License are Attribution and ShareAlike.\n\n  h. Licensed Material means the artistic or literary work, database,\n     or other material to which the Licensor applied this Public\n     License.\n\n  i. Licensed Rights means the rights granted to You subject to the\n     terms and conditions of this Public License, which are limited to\n     all Copyright and Similar Rights that apply to Your use of the\n     Licensed Material and that the Licensor has authority to license.\n\n  j. Licensor means the individual(s) or entity(ies) granting rights\n     under this Public License.\n\n  k. Share means to provide material to the public by any means or\n     process that requires permission under the Licensed Rights, such\n     as reproduction, public display, public performance, distribution,\n     dissemination, communication, or importation, and to make material\n     available to the public including in ways that members of the\n     public may access the material from a place and at a time\n     individually chosen by them.\n\n  l. Sui Generis Database Rights means rights other than copyright\n     resulting from Directive 96/9/EC of the European Parliament and of\n     the Council of 11 March 1996 on the legal protection of databases,\n     as amended and/or succeeded, as well as other essentially\n     equivalent rights anywhere in the world.\n\n  m. You means the individual or entity exercising the Licensed Rights\n     under this Public License. Your has a corresponding meaning.\n\n\nSection 2 -- Scope.\n\n  a. License grant.\n\n       1. Subject to the terms and conditions of this Public License,\n          the Licensor hereby grants You a worldwide, royalty-free,\n          non-sublicensable, non-exclusive, irrevocable license to\n          exercise the Licensed Rights in the Licensed Material to:\n\n            a. reproduce and Share the Licensed Material, in whole or\n               in part; and\n\n            b. produce, reproduce, and Share Adapted Material.\n\n       2. Exceptions and Limitations. For the avoidance of doubt, where\n          Exceptions and Limitations apply to Your use, this Public\n          License does not apply, and You do not need to comply with\n          its terms and conditions.\n\n       3. Term. The term of this Public License is specified in Section\n          6(a).\n\n       4. Media and formats; technical modifications allowed. The\n          Licensor authorizes You to exercise the Licensed Rights in\n          all media and formats whether now known or hereafter created,\n          and to make technical modifications necessary to do so. The\n          Licensor waives and/or agrees not to assert any right or\n          authority to forbid You from making technical modifications\n          necessary to exercise the Licensed Rights, including\n          technical modifications necessary to circumvent Effective\n          Technological Measures. For purposes of this Public License,\n          simply making modifications authorized by this Section 2(a)\n          (4) never produces Adapted Material.\n\n       5. Downstream recipients.\n\n            a. Offer from the Licensor -- Licensed Material. Every\n               recipient of the Licensed Material automatically\n               receives an offer from the Licensor to exercise the\n               Licensed Rights under the terms and conditions of this\n               Public License.\n\n            b. Additional offer from the Licensor -- Adapted Material.\n               Every recipient of Adapted Material from You\n               automatically receives an offer from the Licensor to\n               exercise the Licensed Rights in the Adapted Material\n               under the conditions of the Adapter's License You apply.\n\n            c. No downstream restrictions. You may not offer or impose\n               any additional or different terms or conditions on, or\n               apply any Effective Technological Measures to, the\n               Licensed Material if doing so restricts exercise of the\n               Licensed Rights by any recipient of the Licensed\n               Material.\n\n       6. No endorsement. Nothing in this Public License constitutes or\n          may be construed as permission to assert or imply that You\n          are, or that Your use of the Licensed Material is, connected\n          with, or sponsored, endorsed, or granted official status by,\n          the Licensor or others designated to receive attribution as\n          provided in Section 3(a)(1)(A)(i).\n\n  b. Other rights.\n\n       1. Moral rights, such as the right of integrity, are not\n          licensed under this Public License, nor are publicity,\n          privacy, and/or other similar personality rights; however, to\n          the extent possible, the Licensor waives and/or agrees not to\n          assert any such rights held by the Licensor to the limited\n          extent necessary to allow You to exercise the Licensed\n          Rights, but not otherwise.\n\n       2. Patent and trademark rights are not licensed under this\n          Public License.\n\n       3. To the extent possible, the Licensor waives any right to\n          collect royalties from You for the exercise of the Licensed\n          Rights, whether directly or through a collecting society\n          under any voluntary or waivable statutory or compulsory\n          licensing scheme. In all other cases the Licensor expressly\n          reserves any right to collect such royalties.\n\n\nSection 3 -- License Conditions.\n\nYour exercise of the Licensed Rights is expressly made subject to the\nfollowing conditions.\n\n  a. Attribution.\n\n       1. If You Share the Licensed Material (including in modified\n          form), You must:\n\n            a. retain the following if it is supplied by the Licensor\n               with the Licensed Material:\n\n                 i. identification of the creator(s) of the Licensed\n                    Material and any others designated to receive\n                    attribution, in any reasonable manner requested by\n                    the Licensor (including by pseudonym if\n                    designated);\n\n                ii. a copyright notice;\n\n               iii. a notice that refers to this Public License;\n\n                iv. a notice that refers to the disclaimer of\n                    warranties;\n\n                 v. a URI or hyperlink to the Licensed Material to the\n                    extent reasonably practicable;\n\n            b. indicate if You modified the Licensed Material and\n               retain an indication of any previous modifications; and\n\n            c. indicate the Licensed Material is licensed under this\n               Public License, and include the text of, or the URI or\n               hyperlink to, this Public License.\n\n       2. You may satisfy the conditions in Section 3(a)(1) in any\n          reasonable manner based on the medium, means, and context in\n          which You Share the Licensed Material. For example, it may be\n          reasonable to satisfy the conditions by providing a URI or\n          hyperlink to a resource that includes the required\n          information.\n\n       3. If requested by the Licensor, You must remove any of the\n          information required by Section 3(a)(1)(A) to the extent\n          reasonably practicable.\n\n  b. ShareAlike.\n\n     In addition to the conditions in Section 3(a), if You Share\n     Adapted Material You produce, the following conditions also apply.\n\n       1. The Adapter's License You apply must be a Creative Commons\n          license with the same License Elements, this version or\n          later, or a BY-SA Compatible License.\n\n       2. You must include the text of, or the URI or hyperlink to, the\n          Adapter's License You apply. You may satisfy this condition\n          in any reasonable manner based on the medium, means, and\n          context in which You Share Adapted Material.\n\n       3. You may not offer or impose any additional or different terms\n          or conditions on, or apply any Effective Technological\n          Measures to, Adapted Material that restrict exercise of the\n          rights granted under the Adapter's License You apply.\n\n\nSection 4 -- Sui Generis Database Rights.\n\nWhere the Licensed Rights include Sui Generis Database Rights that\napply to Your use of the Licensed Material:\n\n  a. for the avoidance of doubt, Section 2(a)(1) grants You the right\n     to extract, reuse, reproduce, and Share all or a substantial\n     portion of the contents of the database;\n\n  b. if You include all or a substantial portion of the database\n     contents in a database in which You have Sui Generis Database\n     Rights, then the database in which You have Sui Generis Database\n     Rights (but not its individual contents) is Adapted Material,\n\n     including for purposes of Section 3(b); and\n  c. You must comply with the conditions in Section 3(a) if You Share\n     all or a substantial portion of the contents of the database.\n\nFor the avoidance of doubt, this Section 4 supplements and does not\nreplace Your obligations under this Public License where the Licensed\nRights include other Copyright and Similar Rights.\n\n\nSection 5 -- Disclaimer of Warranties and Limitation of Liability.\n\n  a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE\n     EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS\n     AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF\n     ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,\n     IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,\n     WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR\n     PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,\n     ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT\n     KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT\n     ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.\n\n  b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE\n     TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,\n     NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,\n     INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,\n     COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR\n     USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN\n     ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR\n     DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR\n     IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.\n\n  c. The disclaimer of warranties and limitation of liability provided\n     above shall be interpreted in a manner that, to the extent\n     possible, most closely approximates an absolute disclaimer and\n     waiver of all liability.\n\n\nSection 6 -- Term and Termination.\n\n  a. This Public License applies for the term of the Copyright and\n     Similar Rights licensed here. However, if You fail to comply with\n     this Public License, then Your rights under this Public License\n     terminate automatically.\n\n  b. Where Your right to use the Licensed Material has terminated under\n     Section 6(a), it reinstates:\n\n       1. automatically as of the date the violation is cured, provided\n          it is cured within 30 days of Your discovery of the\n          violation; or\n\n       2. upon express reinstatement by the Licensor.\n\n     For the avoidance of doubt, this Section 6(b) does not affect any\n     right the Licensor may have to seek remedies for Your violations\n     of this Public License.\n\n  c. For the avoidance of doubt, the Licensor may also offer the\n     Licensed Material under separate terms or conditions or stop\n     distributing the Licensed Material at any time; however, doing so\n     will not terminate this Public License.\n\n  d. Sections 1, 5, 6, 7, and 8 survive termination of this Public\n     License.\n\n\nSection 7 -- Other Terms and Conditions.\n\n  a. The Licensor shall not be bound by any additional or different\n     terms or conditions communicated by You unless expressly agreed.\n\n  b. Any arrangements, understandings, or agreements regarding the\n     Licensed Material not stated herein are separate from and\n     independent of the terms and conditions of this Public License.\n\n\nSection 8 -- Interpretation.\n\n  a. For the avoidance of doubt, this Public License does not, and\n     shall not be interpreted to, reduce, limit, restrict, or impose\n     conditions on any use of the Licensed Material that could lawfully\n     be made without permission under this Public License.\n\n  b. To the extent possible, if any provision of this Public License is\n     deemed unenforceable, it shall be automatically reformed to the\n     minimum extent necessary to make it enforceable. If the provision\n     cannot be reformed, it shall be severed from this Public License\n     without affecting the enforceability of the remaining terms and\n     conditions.\n\n  c. No term or condition of this Public License will be waived and no\n     failure to comply consented to unless expressly agreed to by the\n     Licensor.\n\n  d. Nothing in this Public License constitutes or may be interpreted\n     as a limitation upon, or waiver of, any privileges and immunities\n     that apply to the Licensor or You, including from the legal\n     processes of any jurisdiction or authority.\n\n\n=======================================================================\n\nCreative Commons is not a party to its public\nlicenses. Notwithstanding, Creative Commons may elect to apply one of\nits public licenses to material it publishes and in those instances\nwill be considered the “Licensor.” The text of the Creative Commons\npublic licenses is dedicated to the public domain under the CC0 Public\nDomain Dedication. Except for the limited purpose of indicating that\nmaterial is shared under a Creative Commons public license or as\notherwise permitted by the Creative Commons policies published at\ncreativecommons.org/policies, Creative Commons does not authorize the\nuse of the trademark \"Creative Commons\" or any other trademark or logo\nof Creative Commons without its prior written consent including,\nwithout limitation, in connection with any unauthorized modifications\nto any of its public licenses or any other arrangements,\nunderstandings, or agreements concerning use of licensed material. For\nthe avoidance of doubt, this paragraph does not form part of the\npublic licenses.\n\nCreative Commons may be contacted at creativecommons.org.\n"
  },
  {
    "path": "README.md",
    "content": "# Flight rules for Git\n\n🌍\n*[English](README.md) ∙ [Español](README_es.md)  ∙  [Русский](README_ru.md) ∙ [繁體中文](README_zh-TW.md) ∙ [简体中文](README_zh-CN.md) ∙ [한국어](README_kr.md)  ∙  [Tiếng Việt](README_vi.md) ∙ [Français](README_fr.md) ∙ [日本語](README_ja.md)*\n\n#### What are \"flight rules\"?\n\nA guide for astronauts (now, programmers using Git) about what to do when things go wrong.\n\n>  *Flight Rules* are the hard-earned body of knowledge recorded in manuals that list, step-by-step, what to do if X occurs, and why. Essentially, they are extremely detailed, scenario-specific standard operating procedures. [...]\n\n> NASA has been capturing our missteps, disasters and solutions since the early 1960s, when Mercury-era ground teams first started gathering \"lessons learned\" into a compendium that now lists thousands of problematic situations, from engine failure to busted hatch handles to computer glitches, and their solutions.\n\n&mdash; Chris Hadfield, *An Astronaut's Guide to Life on Earth*.\n\n#### Conventions for this document\n\nFor clarity's sake all examples in this document use a customized bash prompt in order to indicate the current branch and whether or not there are staged changes. The branch is enclosed in parentheses, and a `*` next to the branch name indicates staged changes.\n\nAll commands should work for at least git version 2.13.0. See the [git website](https://www.git-scm.com/) to update your local git version.\n\n[![Join the chat at https://gitter.im/k88hudson/git-flight-rules](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/k88hudson/git-flight-rules?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n  - [Repositories](#repositories)\n    - [I want to start a local repository](#i-want-to-start-a-local-repository)\n    - [I want to clone a remote repository](#i-want-to-clone-a-remote-repository)\n    - [I set the wrong remote repository](#i-set-the-wrong-remote-repository)\n    - [I want to add code to someone else's repository](#i-want-to-add-code-to-someone-elses-repository)\n      - [Suggesting code via pull requests](#suggesting-code-via-pull-requests)\n      - [Suggesting code via patches](#suggesting-code-via-patches)\n      - [I need to update my fork with latest updates from the original repository](#i-need-to-update-my-fork-with-latest-updates-from-the-original-repository)\n  - [Editing Commits](#editing-commits)\n    - [What did I just commit?](#what-did-i-just-commit)\n    - [I wrote the wrong thing in a commit message](#i-wrote-the-wrong-thing-in-a-commit-message)\n    - [I committed with the wrong name and email configured](#i-committed-with-the-wrong-name-and-email-configured)\n    - [I want to remove a file from the previous commit](#i-want-to-remove-a-file-from-the-previous-commit)\n    - [I want to move a change from one commit to another](#i-want-to-move-a-change-from-one-commit-to-another)\n    - [I want to delete or remove my last commit](#i-want-to-delete-or-remove-my-last-commit)\n    - [Delete/remove arbitrary commit](#deleteremove-arbitrary-commit)\n    - [I tried to push my amended commit to a remote, but I got an error message](#i-tried-to-push-my-amended-commit-to-a-remote-but-i-got-an-error-message)\n    - [I accidentally did a hard reset, and I want my changes back](#i-accidentally-did-a-hard-reset-and-i-want-my-changes-back)\n    - [I accidentally committed and pushed a merge](#i-accidentally-committed-and-pushed-a-merge)\n    - [I accidentally committed and pushed files containing sensitive data](#i-accidentally-committed-and-pushed-files-containing-sensitive-data)\n    - [I want to remove a large file from ever existing in repo history](#i-want-to-remove-a-large-file-from-ever-existing-in-repo-history)\n      - [Recommended Technique: Use third-party bfg](#recommended-technique-use-third-party-bfg)\n      - [Built-in Technique: Use git-filter-branch](#built-in-technique-use-git-filter-branch)\n      - [Final Step: Pushing your changed repo history](#final-step-pushing-your-changed-repo-history)\n    - [I need to change the content of a commit which is not my last](#i-need-to-change-the-content-of-a-commit-which-is-not-my-last)\n  - [Staging](#staging)\n    - [I want to stage all tracked files and leave untracked files](#i-want-to-stage-all-tracked-files-and-leave-untracked-files)\n      - [To stage part of tracked files](#to-stage-part-of-tracked-files)\n    - [I need to add staged changes to the previous commit](#i-need-to-add-staged-changes-to-the-previous-commit)\n    - [I want to stage part of a new file, but not the whole file](#i-want-to-stage-part-of-a-new-file-but-not-the-whole-file)\n    - [I want to add changes in one file to two different commits](#i-want-to-add-changes-in-one-file-to-two-different-commits)\n    - [I staged too many edits, and I want to break them out into a separate commit](#i-staged-too-many-edits-and-i-want-to-break-them-out-into-a-separate-commit)\n    - [I want to stage my unstaged edits, and unstage my staged edits](#i-want-to-stage-my-unstaged-edits-and-unstage-my-staged-edits)\n    - [I want to unstage a specific staged file](#i-want-to-unstage-a-specific-staged-file)\n  - [Discarding changes](#discarding-changes)\n    - [I want to discard my local uncommitted changes (staged and unstaged)](#i-want-to-discard-my-local-uncommitted-changes-staged-and-unstaged)\n    - [I want to discard specific unstaged changes](#i-want-to-discard-specific-unstaged-changes)\n    - [I want to discard specific unstaged files](#i-want-to-discard-specific-unstaged-files)\n    - [I want to discard only my unstaged local changes](#i-want-to-discard-only-my-unstaged-local-changes)\n    - [I want to discard all of my untracked files](#i-want-to-discard-all-of-my-untracked-files)\n  - [Branches](#branches)\n    - [I want to list all branches](#i-want-to-list-all-branches)\n    - [Create a branch from a commit](#create-a-branch-from-a-commit)\n    - [I pulled from/into the wrong branch](#i-pulled-frominto-the-wrong-branch)\n    - [I want to discard local commits so my branch is the same as one on the server](#i-want-to-discard-local-commits-so-my-branch-is-the-same-as-one-on-the-server)\n    - [I want to move my unstaged edits to a new branch](#i-want-to-move-my-unstaged-edits-to-a-new-branch)\n    - [I want to move my unstaged edits to a different, existing branch](#i-want-to-move-my-unstaged-edits-to-a-different-existing-branch)\n    - [I committed to main instead of a new branch](#i-committed-to-main-instead-of-a-new-branch)\n    - [I want to keep the whole file from another ref-ish](#i-want-to-keep-the-whole-file-from-another-ref-ish)\n    - [I made several commits on a single branch that should be on different branches](#i-made-several-commits-on-a-single-branch-that-should-be-on-different-branches)\n    - [I want to delete local branches that were deleted upstream](#i-want-to-delete-local-branches-that-were-deleted-upstream)\n    - [I accidentally deleted my branch](#i-accidentally-deleted-my-branch)\n    - [I want to delete a branch](#i-want-to-delete-a-branch)\n    - [I want to delete multiple branches](#i-want-to-delete-multiple-branches)\n    - [I want to rename a branch](#i-want-to-rename-a-branch)\n    - [I want to checkout to a remote branch that someone else is working on](#i-want-to-checkout-to-a-remote-branch-that-someone-else-is-working-on)\n    - [I want to create a new remote branch from current local one](#i-want-to-create-a-new-remote-branch-from-current-local-one)\n    - [I want to set a remote branch as the upstream for a local branch](#i-want-to-set-a-remote-branch-as-the-upstream-for-a-local-branch)\n    - [I want to set my HEAD to track the default remote branch](#i-want-to-set-my-head-to-track-the-default-remote-branch)\n    - [I made changes on the wrong branch](#i-made-changes-on-the-wrong-branch)\n    - [I want to split a branch into two](#i-want-to-split-a-branch-into-two)\n  - [Rebasing and Merging](#rebasing-and-merging)\n    - [I want to undo rebase/merge](#i-want-to-undo-rebasemerge)\n    - [I rebased, but I don't want to force push](#i-rebased-but-i-dont-want-to-force-push)\n    - [I need to combine commits](#i-need-to-combine-commits)\n      - [Safe merging strategy](#safe-merging-strategy)\n      - [I need to merge a branch into a single commit](#i-need-to-merge-a-branch-into-a-single-commit)\n      - [I want to combine only unpushed commits](#i-want-to-combine-only-unpushed-commits)\n      - [I need to abort the merge](#i-need-to-abort-the-merge)\n    - [I need to update the parent commit of my branch](#i-need-to-update-the-parent-commit-of-my-branch)\n    - [Check if all commits on a branch are merged](#check-if-all-commits-on-a-branch-are-merged)\n    - [Possible issues with interactive rebases](#possible-issues-with-interactive-rebases)\n      - [The rebase editing screen says 'noop'](#the-rebase-editing-screen-says-noop)\n      - [There were conflicts](#there-were-conflicts)\n  - [Stash](#stash)\n    - [Stash all edits](#stash-all-edits)\n    - [Stash specific files](#stash-specific-files)\n    - [Stash with message](#stash-with-message)\n    - [Apply a specific stash from list](#apply-a-specific-stash-from-list)\n    - [Stash while keeping unstaged edits](#stash-while-keeping-unstaged-edits)\n  - [Finding](#finding)\n    - [I want to find a string in any commit](#i-want-to-find-a-string-in-any-commit)\n    - [I want to find by author/committer](#i-want-to-find-by-authorcommitter)\n    - [I want to list commits containing specific files](#i-want-to-list-commits-containing-specific-files)\n    - [I want to view the commit history for a specific function](#i-want-to-view-the-commit-history-for-a-specific-function)\n    - [Find a tag where a commit is referenced](#find-a-tag-where-a-commit-is-referenced)\n  - [Submodules](#submodules)\n    - [Clone all submodules](#clone-all-submodules)\n    - [Remove a submodule](#remove-a-submodule)\n  - [Miscellaneous Objects](#miscellaneous-objects)\n    - [Copy a folder or file from one branch to another](#copy-a-folder-or-file-from-one-branch-to-another)\n    - [Restore a deleted file](#restore-a-deleted-file)\n    - [Delete tag](#delete-tag)\n    - [Recover a deleted tag](#recover-a-deleted-tag)\n    - [Deleted Patch](#deleted-patch)\n    - [Exporting a repository as a Zip file](#exporting-a-repository-as-a-zip-file)\n    - [Push a branch and a tag that have the same name](#push-a-branch-and-a-tag-that-have-the-same-name)\n  - [Tracking Files](#tracking-files)\n    - [I want to change a file name's capitalization, without changing the contents of the file](#i-want-to-change-a-file-names-capitalization-without-changing-the-contents-of-the-file)\n    - [I want to overwrite local files when doing a git pull](#i-want-to-overwrite-local-files-when-doing-a-git-pull)\n    - [I want to remove a file from Git but keep the file](#i-want-to-remove-a-file-from-git-but-keep-the-file)\n    - [I want to revert a file to a specific revision](#i-want-to-revert-a-file-to-a-specific-revision)\n    - [I want to list changes of a specific file between commits or branches](#i-want-to-list-changes-of-a-specific-file-between-commits-or-branches)\n    - [I want Git to ignore changes to a specific file](#i-want-git-to-ignore-changes-to-a-specific-file)\n  - [Debugging with Git](#debugging-with-git)\n  - [Configuration](#configuration)\n    - [I want to add aliases for some Git commands](#i-want-to-add-aliases-for-some-git-commands)\n    - [I want to add an empty directory to my repository](#i-want-to-add-an-empty-directory-to-my-repository)\n    - [I want to cache a username and password for a repository](#i-want-to-cache-a-username-and-password-for-a-repository)\n    - [I want to make Git ignore permissions and filemode changes](#i-want-to-make-git-ignore-permissions-and-filemode-changes)\n    - [I want to set a global user](#i-want-to-set-a-global-user)\n  - [I've no idea what I did wrong](#ive-no-idea-what-i-did-wrong)\n  - [Git Shortcuts](#git-shortcuts)\n    - [Git Bash](#git-bash)\n    - [PowerShell on Windows](#powershell-on-windows)\n- [Other Resources](#other-resources)\n  - [Books](#books)\n  - [Tutorials](#tutorials)\n  - [Scripts and Tools](#scripts-and-tools)\n  - [GUI Clients](#gui-clients)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n## Repositories\n\n### I want to start a local repository\n\nTo initialize an existing directory as a Git repository:\n\n```sh\n(my-folder) $ git init\n```\n\n### I want to clone a remote repository\n\nTo clone (copy) a remote repository, copy the URL for the repository, and run:\n\n```sh\n$ git clone [url]\n```\n\nThis will save it to a folder named the same as the remote repository's. Make sure you have a connection to the remote server you are cloning from (for most purposes this means making sure you are connected to the internet).\n\nTo clone it into a folder with a different name than the default repository name:\n\n```sh\n$ git clone [url] name-of-new-folder\n```\n\n### I set the wrong remote repository\n\nThere are a few possible problems here:\n\nIf you cloned the wrong repository, simply delete the directory created after running `git clone` and clone the correct repository.\n\nIf you set the wrong repository as the origin of an existing local repository, change the URL of your origin by running:\n\n```sh\n$ git remote set-url origin [url of the actual repo]\n```\n\nFor more, see [this StackOverflow topic](https://stackoverflow.com/questions/2432764/how-to-change-the-uri-url-for-a-remote-git-repository#2432799).\n\n\n### I want to add code to someone else's repository\n\nGit doesn't allow you to add code to someone else's repository without access rights. Neither does GitHub, which is not the same as Git, but rather a hosted service for Git repositories. However, you can suggest code using patches, or, on GitHub, forks and pull requests.\n\nFirst, a bit about forking. A fork is a copy of a repository. It is not a git operation, but is a common action on GitHub, Bitbucket, GitLab — or anywhere people host Git repositories. You can fork a repository through the hosted UI.\n\n#### Suggesting code via pull requests\n\nAfter you've forked a repository, you normally need to clone the repository to your machine. You can do some small edits on GitHub, for instance, without cloning, but this isn't a github-flight-rules list, so let's go with how to do this locally.\n\n```sh\n# if you are using ssh\n$ git clone git@github.com:k88hudson/git-flight-rules.git\n\n# if you are using https\n$ git clone https://github.com/k88hudson/git-flight-rules.git\n```\n\nIf you `cd` into the resulting directory, and type `git remote`, you'll see a list of the remotes. Normally there will be one remote - `origin` - which will point to `k88hudson/git-flight-rules`. In this case, we also want a remote that will point to your fork.\n\nFirst, to follow a Git convention, we normally use the remote name `origin` for your own repository and `upstream` for whatever you've forked. So, rename the `origin` remote to `upstream`\n\n```sh\n$ git remote rename origin upstream\n```\n\nYou can also do this using `git remote set-url`, but it takes longer and is more steps.\n\nThen, set up a new remote that points to your project.\n\n```sh\n$ git remote add origin git@github.com:YourName/git-flight-rules.git\n```\n\nNote that now you have two remotes.\n\n- `origin` references your own repository.\n- `upstream` references the original one.\n\nFrom origin, you can read and write. From upstream, you can only read.\n\nWhen you've finished making whatever changes you like, push your changes (normally in a branch) to the remote named `origin`. If you're on a branch, you could use `--set-upstream` to avoid specifying the remote tracking branch on every future push using this branch. For instance:\n\n```sh\n$ (feature/my-feature) git push --set-upstream origin feature/my-feature\n```\n\nThere is no way to suggest a pull request using the CLI using Git (although there are tools, like [hub](http://github.com/github/hub), which will do this for you). So, if you're ready to make a pull request, go to your GitHub (or another Git host) and create a new pull request. Note that your host automatically links the original and forked repositories.\n\nAfter all of this, do not forget to respond to any code review feedback.\n\n#### Suggesting code via patches\n\nAnother approach to suggesting code changes that doesn't rely on third party sites such as Github is to use `git format-patch`.\n\n`format-patch` creates a .patch file for one or more commits. This file is essentially a list of changes that looks similar to the commit diffs you can view on Github.\n\nA patch can be viewed and even edited by the recipient and applied using `git am`.\n\nFor example, to create a patch based on the previous commit you would run `git format-patch HEAD^` which would create a .patch file called something like 0001-My-Commit-Message.patch.\n\nTo apply this patch file to your repository you would run `git am ./0001-My-Commit-Message.patch`.\n\nPatches can also be sent via email using the `git send-email` command. For information on usage and configuration see: https://git-send-email.io\n\n#### I need to update my fork with latest updates from the original repository\n\nAfter a while, the `upstream` repository may have been updated, and these updates need to be pulled into your `origin` repo. Remember that like you, other people are contributing too. Suppose that you are in your own feature branch and you need to update it with the original repository updates.\n\nYou probably have set up a remote that points to the original project. If not, do this now. Generally we use `upstream` as a remote name:\n\n```sh\n$ (main) git remote add upstream <link-to-original-repository>\n# $ (main) git remote add upstream git@github.com:k88hudson/git-flight-rules.git\n```\n\nNow you can fetch from upstream and get the latest updates.\n\n```sh\n$ (main) git fetch upstream\n$ (main) git merge upstream/main\n\n# or using a single command\n$ (main) git pull upstream main\n```\n\n## Editing Commits\n\n<a name=\"diff-last\"></a>\n### What did I just commit?\n\nLet's say that you just blindly committed changes with `git commit -a` and you're not sure what the actual content of the commit you just made was. You can show the latest commit on your current HEAD with:\n\n```sh\n(main)$ git show\n```\n\nOr\n\n```sh\n$ git log -n1 -p\n```\n\nIf you want to see a file at a specific commit, you can also do this (where `<commitid>` is the commit you're interested in):\n\n```sh\n$ git show <commitid>:filename\n```\n\n<a name=\"wrong-thing-in-commit-message\"></a>\n### I wrote the wrong thing in a commit message\n\nIf you wrote the wrong thing and the commit has not yet been pushed, you can do the following to change the commit message without changing the changes in the commit:\n\n```sh\n$ git commit --amend --only\n```\n\nThis will open your default text editor, where you can edit the message. On the other hand, you can do this all in one command:\n\n```sh\n$ git commit --amend --only -m 'xxxxxxx'\n```\n\nIf you have already pushed the message, you can amend the commit and force push, but this is not recommended.\n\n<a name=\"commit-wrong-author\"></a>\n### I committed with the wrong name and email configured\n\nIf it's a single commit, amend it\n\n```sh\n$ git commit --amend --no-edit --author \"New Authorname <authoremail@mydomain.com>\"\n```\n\nAn alternative is to correctly configure your author settings in `git config --global author.(name|email)` and then use\n\n```sh\n$ git commit --amend --reset-author --no-edit\n```\n\nIf you need to change for multiple commits, you can use\n\n```sh\n$ git -c rebase.instructionFormat='%s%nexec GIT_COMMITTER_DATE=\"%cD\" GIT_AUTHOR_DATE=\"%aD\" git commit --amend --no-edit --reset-author' rebase -r <commit>\n```\n\n`<commit>` is a commit before all your bad commits. If you need to change all of history in the current branch including the root of the branch, put `--root` there instead.\n\nIf you need to change all of history, see the man page for `git filter-branch`.\n\nNote this will change the history and a force push is required.\n\n### I want to remove a file from the previous commit\n\nIn order to remove changes for a file from the previous commit, do the following:\n\n```sh\n$ git checkout HEAD^ myfile\n$ git add myfile\n$ git commit --amend --no-edit\n```\n\nIn case the file was newly added to the commit and you want to remove it (from Git alone), do:\n\n```sh\n$ git rm --cached myfile\n$ git commit --amend --no-edit\n```\n\nThis is particularly useful when you have an open patch and you have committed an unnecessary file, and need to force push to update the patch on a remote. The `--no-edit` option is used to keep the existing commit message.\n\n<a name=\"move-change-to-new-commit\"></a>\n### I want to move a change from one commit to another\nIf you've made a commit that includes changes that would fit better in another commit, you can move the changes to the other commit using an interactive rebase. This comes from [stackoverflow](https://stackoverflow.com/a/54985304/2491502).\n\nFor example, you have three commits (a, b, c). On b, you've changes file1 and file2 and you want to move the change on file1 from commit b to commit a.\n\nFirst, rebase interactively:\n\n```sh\n$ git rebase -i HEAD~3\n```\n\nThis will open an editor with the following:\n\n```sh\npick a\npick b\npick c\n```\n\nChange the lines with a and b to edit:\n\n```sh\nedit a\nedit b\npick c\n```\n\nSave and close the editor. This will bring you to commit b. Now, reset the file1 changes:\n\n```sh\n$ git reset HEAD~1 file1\n```\n\nThis will unstage the changes in file1. Now, stash those changes and continue the rebase:\n\n```sh\n$ git stash\n$ git rebase --continue\n```\n\nNow you will be editing commit a. Unstash the changes then add them to the current commit and continue the rebase:\n\n```sh\n$ git stash pop\n$ git add file1\n$ git commit --amend --no-edit\n$ git rebase --continue\n```\n\nNow your rebase is complete, with the changes from b on a. If you wanted to move the changes from b to c, you would have to do two rebases since c comes before b: one to get the changes out of b, then another to edit c and add the stashed changes.\n\n<a name=\"delete-pushed-commit\"></a>\n### I want to delete or remove my last commit\n\nIf you need to delete pushed commits, you can use the following. However, it will irreversibly change your history, and mess up the history of anyone else who had already pulled from the repository. In short, if you're not sure, you should never do this, ever.\n\n```sh\n$ git reset HEAD^ --hard\n$ git push --force-with-lease [remote] [branch]\n```\n\nIf you haven't pushed, to reset Git to the state it was in before you made your last commit (while keeping your staged changes):\n\n```\n(my-branch)$ git reset --soft HEAD^\n```\n\nThis only works if you haven't pushed. If you have pushed, the only truly safe thing to do is `git revert SHAofBadCommit`. That will create a new commit that undoes all the previous commit's changes. Or, if the branch you pushed to is rebase-safe (ie. other devs aren't expected to pull from it), you can just use `git push --force-with-lease`. For more, see [the above section](#deleteremove-last-pushed-commit).\n\n<a name=\"delete-any-commit\"></a>\n### Delete/remove arbitrary commit\n\nThe same warning applies as above. Never do this if possible.\n\n```sh\n$ git rebase --onto SHA1_OF_BAD_COMMIT^ SHA1_OF_BAD_COMMIT\n$ git push --force-with-lease [remote] [branch]\n```\n\nOr do an [interactive rebase](#interactive-rebase) and remove the line(s) corresponding to commit(s) you want to see removed.\n\n<a name=\"force-push\"></a>\n### I tried to push my amended commit to a remote, but I got an error message\n\n```sh\nTo https://github.com/yourusername/repo.git\n! [rejected]        mybranch -> mybranch (non-fast-forward)\nerror: failed to push some refs to 'https://github.com/tanay1337/webmaker.org.git'\nhint: Updates were rejected because the tip of your current branch is behind\nhint: its remote counterpart. Integrate the remote changes (e.g.\nhint: 'git pull ...') before pushing again.\nhint: See the 'Note about fast-forwards' in 'git push --help' for details.\n```\n\nNote that, as with rebasing (see below), amending **replaces the old commit with a new one**, so you must force push (`--force-with-lease`) your changes if you have already pushed the pre-amended commit to your remote. Be careful when you do this &ndash; *always* make sure you specify a branch!\n\n```sh\n(my-branch)$ git push origin mybranch --force-with-lease\n```\n\nIn general, **avoid force pushing**. It is best to create and push a new commit rather than force-pushing the amended commit as it will cause conflicts in the source history for any other developer who has interacted with the branch in question or any child branches. `--force-with-lease` will still fail, if someone else was also working on the same branch as you, and your push would overwrite those changes.\n\nIf you are *absolutely* sure that nobody is working on the same branch or you want to update the tip of the branch *unconditionally*, you can use `--force` (`-f`), but this should be avoided in general.\n\n<a name=\"undo-git-reset-hard\"></a>\n### I accidentally did a hard reset, and I want my changes back\n\nIf you accidentally do `git reset --hard`, you can normally still get your commit back, as git keeps a log of everything for a few days.\n\nNote: This is only valid if your work is backed up, i.e., either committed or stashed. `git reset --hard` _will remove_ uncommitted modifications, so use it with caution. (A safer option is `git reset --keep`.)\n\n```sh\n(main)$ git reflog\n```\n\nYou'll see a list of your past commits, and a commit for the reset. Choose the SHA of the commit you want to return to, and reset again:\n\n```sh\n(main)$ git reset --hard SHA1234\n```\n\nAnd you should be good to go.\n\n<a name=\"undo-a-commit-merge\"></a>\n### I accidentally committed and pushed a merge\n\nIf you accidentally merged a feature branch to the main development branch before it was ready to be merged, you can still undo the merge. But there's a catch: A merge commit has more than one parent (usually two).\n\nThe command to use\n```sh\n(feature-branch)$ git revert -m 1 <commit>\n```\nwhere the -m 1 option says to select parent number 1 (the branch into which the merge was made) as the parent to revert to.\n\nNote: the parent number is not a commit identifier. Rather, a merge commit has a line `Merge: 8e2ce2d 86ac2e7`. The parent number is the 1-based index of the desired parent on this line, the first identifier is number 1, the second is number 2, and so on.\n\n<a name=\"undo-sensitive-commit-push\"></a>\n### I accidentally committed and pushed files containing sensitive data\n\nIf you accidentally pushed files containing sensitive, or private data (passwords, keys, etc.), you can amend the previous commit. Keep in mind that once you have pushed a commit, you should consider any data it contains to be compromised. These steps can remove the sensitive data from your public repo or your local copy, but you **cannot** remove the sensitive data from other people's pulled copies. If you committed a password, **change it immediately**. If you committed a key, **re-generate it immediately**. Amending the pushed commit is not enough, since anyone could have pulled the original commit containing your sensitive data in the meantime.\n\nIf you edit the file and remove the sensitive data, then run\n```sh\n(feature-branch)$ git add edited_file\n(feature-branch)$ git commit --amend --no-edit\n(feature-branch)$ git push --force-with-lease origin [branch]\n```\n\nIf you want to remove an entire file (but keep it locally), then run\n```sh\n(feature-branch)$ git rm --cached sensitive_file\necho sensitive_file >> .gitignore\n(feature-branch)$ git add .gitignore\n(feature-branch)$ git commit --amend --no-edit\n(feature-branch)$ git push --force-with-lease origin [branch]\n```\nAlternatively store your sensitive data in local environment variables.\n\nIf you want to completely remove an entire file (and not keep it locally), then run\n\n```sh\n(feature-branch)$ git rm sensitive_file\n(feature-branch)$ git commit --amend --no-edit\n(feature-branch)$ git push --force-with-lease origin [branch]\n```\n\nIf you have made other commits in the meantime (i.e. the sensitive data is in a commit before the previous commit), you will have to rebase.\n\n<a name=\"remove-large-file-in-repo-history\"></a>\n### I want to remove a large file from ever existing in repo history\n\nIf the file you want to delete is secret or sensitive, instead see [how to remove sensitive files](#undo-sensitive-commit-push).\n\nEven if you delete a large or unwanted file in a recent commit, it still exists in git history, in your repo's `.git` folder, and will make `git clone` download unneeded files.\n\nThe actions in this part of the guide will require a force push, and rewrite large sections of repo history, so if you are working with remote collaborators, check first that any local work of theirs is pushed.\n\nThere are two options for rewriting history, the built-in `git-filter-branch` or [`bfg-repo-cleaner`](https://rtyley.github.io/bfg-repo-cleaner/). `bfg` is significantly cleaner and more performant, but it is a third-party download and requires java. We will describe both alternatives. The final step is to force push your changes, which requires special consideration on top of a regular force push, given that a great deal of repo history will have been permanently changed.\n\n#### Recommended Technique: Use third-party bfg\n\nUsing bfg-repo-cleaner requires java. Download the bfg jar from the link [here](https://rtyley.github.io/bfg-repo-cleaner/). Our examples will use `bfg.jar`, but your download may have a version number, e.g. `bfg-1.13.0.jar`.\n\nTo delete a specific file.\n\n```sh\n(main)$ git rm path/to/filetoremove\n(main)$ git commit -m \"Commit removing filetoremove\"\n(main)$ java -jar ~/Downloads/bfg.jar --delete-files filetoremove\n```\n\nNote that in bfg you must use the plain file name even if it is in a subdirectory.\n\nYou can also delete a file by pattern, e.g.:\n\n```sh\n(main)$ git rm *.jpg\n(main)$ git commit -m \"Commit removing *.jpg\"\n(main)$ java -jar ~/Downloads/bfg.jar --delete-files *.jpg\n```\n\nWith bfg, the files that exist on your latest commit will not be affected. For example, if you had several large .tga files in your repo, and then in an earlier commit, you deleted a subset of them, this call does not touch files present in the latest commit\n\nNote, if you renamed a file as part of a commit, e.g. if it started as `LargeFileFirstName.mp4` and a commit changed it to `LargeFileSecondName.mp4`, running `java -jar ~/Downloads/bfg.jar --delete-files LargeFileSecondName.mp4` will not remove it from git history. Either run the `--delete-files` command with both filenames, or with a matching pattern.\n\n#### Built-in Technique: Use git-filter-branch\n\n`git-filter-branch` is more cumbersome and has less features, but you may use it if you cannot install or run `bfg`.\n\nIn the below, replace `filepattern` may be a specific name or pattern, e.g. `*.jpg`. This will remove files matching the pattern from all history and branches.\n\n```sh\n(main)$ git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch filepattern' --prune-empty --tag-name-filter cat -- --all\n```\n\nBehind-the-scenes explanation:\n\n`--tag-name-filter cat` is a cumbersome, but simplest, way to apply the original tags to the new commits, using the command cat.\n\n`--prune-empty` removes any now-empty commits.\n\n#### Final Step: Pushing your changed repo history\n\nOnce you have removed your desired files, test carefully that you haven't broken anything in your repo - if you have, it is easiest to re-clone your repo to start over.\nTo finish, optionally use git garbage collection to minimize your local .git folder size, and then force push.\n```sh\n(main)$ git reflog expire --expire=now --all && git gc --prune=now --aggressive\n(main)$ git push origin --force --tags\n```\n\nSince you just rewrote the entire git repo history, the `git push` operation may be too large, and return the error `“The remote end hung up unexpectedly”`. If this happens, you can try increasing the git post buffer:\n```sh\n(main)$ git config http.postBuffer 524288000\n(main)$ git push --force\n```\n\nIf this does not work, you will need to manually push the repo history in chunks of commits. In the command below, try increasing `<number>` until the push operation succeeds.\n```sh\n(main)$ git push -u origin HEAD~<number>:refs/head/main --force\n```\nOnce the push operation succeeds the first time, decrease `<number>` gradually until a conventional `git push` succeeds.\n\n<a name=\"change-content-of-commit-not-my-last\"></a>\n### I need to change the content of a commit which is not my last\n\nConsider you created some (e.g. three) commits and later realize you missed doing something that belongs contextually into the first of those commits. This bothers you, because if you'd create a new commit containing those changes, you'd have a clean code base, but your commits weren't atomic (i.e. changes that belonged to each other weren't in the same commit). In such a situation you may want to change the commit where these changes belong to, include them and have the following commits unaltered. In such a case, `git rebase` might save you.\n\nConsider a situation where you want to change the third last commit you made.\n\n```sh\n(your-branch)$ git rebase -i HEAD~4\n```\n\ngets you into interactive rebase mode, which allows you to edit any of your last three commits. A text editor pops up, showing you something like\n\n```sh\npick 9e1d264 The third last commit\npick 4b6e19a The second to last commit\npick f4037ec The last commit\n```\n\nwhich you change into\n\n```sh\nedit 9e1d264 The third last commit\npick 4b6e19a The second to last commit\npick f4037ec The last commit\n```\n\nThis tells rebase that you want to edit your third last commit and keep the other two unaltered. Then you'll save (and close) the editor. Git will then start to rebase. It stops on the commit you want to alter, giving you the chance to edit that commit. Now you can apply the changes which you missed applying when you initially committed that commit. You do so by editing and staging them. Afterwards you'll run\n\n```sh\n(your-branch)$ git commit --amend\n```\n\nwhich tells Git to recreate the commit. Also, Git will ask you to write a new commit message, using the original commit message as a starting point. Having done that, the hard part is solved.\n\n```sh\n(your-branch)$ git rebase --continue\n```\n\nwill do the rest of the work for you.\n\n## Staging\n\n<a name=\"stage-tracked-files-and-leave-untracked-files\"></a>\n### I want to stage all tracked files and leave untracked files\n\n```sh\n$ git add -u\n```\n\n#### To stage part of tracked files\n\n```sh\n# to stage files with ext .txt\n$ git add -u *.txt\n\n# to stage all files inside directory src\n$ git add -u src/\n```\n\n<a name=\"add-staged-changes-to-previous-commit\"></a>\n### I need to add staged changes to the previous commit\n\n```sh\n(my-branch*)$ git commit --amend\n```\n\nIf you already know you don't want to change the commit message, you can tell git to reuse the commit message:\n\n```sh\n(my-branch*)$ git commit --amend -C HEAD\n```\n\n<a name=\"commit-partial-new-file\"></a>\n### I want to stage part of a new file, but not the whole file\n\nNormally, if you want to stage part of a file, you run this:\n\n```sh\n$ git add --patch filename.x\n```\n\n`-p` will work for short. This will open interactive mode. You would be able to use the `s` option to split the commit - however, if the file is new, you will not have this option. To add a new file, do this:\n\n```sh\n$ git add -N filename.x\n```\n\nThen, you will need to use the `e` option to manually choose which lines to add. Running `git diff --cached` or\n`git diff --staged` will show you which lines you have staged compared to which are still saved locally.\n\n<a name=\"stage-in-two-commits\"></a>\n### I want to add changes in one file to two different commits\n\n`git add` will add the entire file to a commit. `git add -p` will allow to interactively select which changes you want to add.\n\n<a name=\"selective-unstage-edits\"></a>\n### I staged too many edits, and I want to break them out into a separate commit\n\n`git reset -p` will open a patch mode reset dialog.  This is similar to `git add -p`, except that selecting \"yes\" will unstage the change, removing it from the upcoming commit.\n\n<a name=\"unstaging-edits-and-staging-the-unstaged\"></a>\n### I want to stage my unstaged edits, and unstage my staged edits\n\nIn many cases, you should unstage all of your staged files and then pick the file you want and commit it. However, if you want to switch the staged and unstaged edits, you can create a temporary commit to store your staged files, stage your unstaged files and then stash them. Then, reset the temporary commit and pop your stash.\n\n```sh\n$ git commit -m \"WIP\"\n$ git add . # This will also add untracked files.\n$ git stash\n$ git reset HEAD^\n$ git stash pop --index 0\n```\n\nNOTE 1: The reason to use `pop` here is want to keep idempotent as much as possible.\nNOTE 2: Your staged files will be marked as unstaged if you don't use the `--index` flag. ([This link](https://stackoverflow.com/questions/31595873/git-stash-with-staged-files-does-stash-convert-staged-files-to-unstaged?answertab=active#tab-top) explains why.)\n\n<a name=\"unstage-specific-staged-file\"></a>\n### I want to unstage a specific staged file\n\nSometimes we have one or more files that accidentally ended up being staged, and these files have not been committed before. To unstage them:\n\n```sh\n$ git reset -- <filename>\n```\n\nThis results in unstaging the file and make it look like it's untracked.\n\n## Discarding changes\n\n<a name=\"discard-local-uncommitted-changes\"></a>\n### I want to discard my local uncommitted changes (staged and unstaged)\n\nIf you want to discard all your local staged and unstaged changes, you can do this:\n\n```sh\n(my-branch)$ git reset --hard\n# or\n(main)$ git checkout -f\n```\n\nThis will unstage all files you might have staged with `git add`:\n\n```sh\n$ git reset\n```\n\nThis will revert all local uncommitted changes (should be executed in repo root):\n\n```sh\n$ git checkout .\n```\n\nYou can also revert uncommitted changes to a particular file or directory:\n\n```sh\n$ git checkout [some_dir|file.txt]\n```\n\nYet another way to revert all uncommitted changes (longer to type, but works from any subdirectory):\n\n```sh\n$ git reset --hard HEAD\n```\n\nThis will remove all local untracked files, so only files tracked by Git remain:\n\n```sh\n$ git clean -fd\n```\n\n`-x` will also remove all ignored files.\n\n### I want to discard specific unstaged changes\n\nWhen you want to get rid of some, but not all changes in your working copy.\n\nCheckout undesired changes, keep good changes.\n\n```sh\n$ git checkout -p\n# Answer y to all of the snippets you want to drop\n```\n\nAnother strategy involves using `stash`. Stash all the good changes, reset working copy, and reapply good changes.\n\n```sh\n$ git stash -p\n# Select all of the snippets you want to save\n$ git reset --hard\n$ git stash pop\n```\n\nAlternatively, stash your undesired changes, and then drop stash.\n\n```sh\n$ git stash -p\n# Select all of the snippets you don't want to save\n$ git stash drop\n```\n\n### I want to discard specific unstaged files\n\nWhen you want to get rid of one specific file in your working copy.\n\n```sh\n$ git checkout myFile\n```\n\nAlternatively, to discard multiple files in your working copy, list them all.\n\n```sh\n$ git checkout myFirstFile mySecondFile\n```\n\n### I want to discard only my unstaged local changes\n\nWhen you want to get rid of all of your unstaged local uncommitted changes\n\n```sh\n$ git checkout .\n```\n<a name=\"discard-all-untracked-files\"></a>\n### I want to discard all of my untracked files\n\nWhen you want to get rid of all of your untracked files\n\n```sh\n$ git clean -f\n```\n\n## Branches\n\n### I want to list all branches\n\nList local branches\n\n```sh\n$ git branch\n```\n\nList remote branches\n\n```sh\n$ git branch -r\n```\n\nList all branches (both local and remote)\n\n```sh\n$ git branch -a\n```\n\n<a name=\"create-branch-from-commit\"></a>\n### Create a branch from a commit\n```sh\n$ git checkout -b <branch> <SHA1_OF_COMMIT>\n```\n\n<a name=\"pull-wrong-branch\"></a>\n### I pulled from/into the wrong branch\n\nThis is another chance to use `git reflog` to see where your HEAD pointed before the bad pull.\n\n```sh\n(main)$ git reflog\nab7555f HEAD@{0}: pull origin wrong-branch: Fast-forward\nc5bc55a HEAD@{1}: checkout: checkout message goes here\n```\n\nSimply reset your branch back to the desired commit:\n\n```sh\n$ git reset --hard c5bc55a\n```\n\nDone.\n\n<a name=\"discard-local-commits\"></a>\n### I want to discard local commits so my branch is the same as one on the server\n\nConfirm that you haven't pushed your changes to the server.\n\n`git status` should show how many commits you are ahead of origin:\n\n```sh\n(my-branch)$ git status\n# On branch my-branch\n# Your branch is ahead of 'origin/my-branch' by 2 commits.\n#   (use \"git push\" to publish your local commits)\n#\n```\n\nOne way of resetting branch `my-branch` to match `origin/my-branch` (to have the same as what is on the remote) is to do this:\n\n```sh\n(my-branch)$ git reset --hard origin/my-branch\n```\n\n<a name=\"move-unstaged-edits-to-new-branch\"></a>\n### I want to move my unstaged edits to a new branch\n\n```sh\n$ git checkout -b my-branch\n```\n\n<a name=\"move-unstaged-edits-to-old-branch\"></a>\n### I want to move my unstaged edits to a different, existing branch\n\n```sh\n$ git stash\n$ git checkout my-branch\n$ git stash pop\n```\n\n<a name=\"commit-wrong-branch\"></a>\n### I committed to main instead of a new branch\n\nCreate the new branch while remaining on main:\n\n```sh\n(main)$ git branch my-branch\n```\n\nReset the branch main to the previous commit:\n\n```sh\n(main)$ git reset --hard HEAD^\n```\n\n`HEAD^` is short for `HEAD^1`. This stands for the first parent of `HEAD`, similarly `HEAD^2` stands for the second parent of the commit (merges can have 2 parents).\n\nNote that `HEAD^2` is **not** the same as `HEAD~2` (see [this link](http://www.paulboxley.com/blog/2011/06/git-caret-and-tilde) for more information).\n\nAlternatively, if you don't want to use `HEAD^`, find out what the commit hash you want to set your main branch to (`git log` should do the trick). Then reset to that hash. `git push` will make sure that this change is reflected on your remote.\n\nFor example, if the hash of the commit that your main branch is supposed to be at is `a13b85e`:\n\n```sh\n(main)$ git reset --hard a13b85e\nHEAD is now at a13b85e\n```\n\nCheckout the new branch to continue working:\n\n```sh\n(main)$ git checkout my-branch\n```\n\n<a name=\"keep-whole-file\"></a>\n### I want to keep the whole file from another ref-ish\n\nSay you have a working spike (see note), with hundreds of changes. Everything is working. Now, you commit into another branch to save that work:\n\n```sh\n(solution)$ git add -A && git commit -m \"Adding all changes from this spike into one big commit.\"\n```\n\nWhen you want to put it into a branch (maybe feature, maybe `develop`), you're interested in keeping whole files. You want to split your big commit into smaller ones.\n\nSay you have:\n\n  * branch `solution`, with the solution to your spike. One ahead of `develop`.\n  * branch `develop`, where you want to add your changes.\n\nYou can solve it bringing the contents to your branch:\n\n```sh\n(develop)$ git checkout solution -- file1.txt\n```\n\nThis will get the contents of that file in branch `solution` to your branch `develop`:\n\n```sh\n# On branch develop\n# Your branch is up-to-date with 'origin/develop'.\n# Changes to be committed:\n#  (use \"git reset HEAD <file>...\" to unstage)\n#\n#        modified:   file1.txt\n```\n\nThen, commit as usual.\n\nNote: Spike solutions are made to analyze or solve the problem. These solutions are used for estimation and discarded once everyone gets clear visualization of the problem. ~ [Wikipedia](https://en.wikipedia.org/wiki/Extreme_programming_practices).\n\n<a name=\"cherry-pick\"></a>\n### I made several commits on a single branch that should be on different branches\n\nSay you are on your main branch. Running `git log`, you see you have made two commits:\n\n```sh\n(main)$ git log\n\ncommit e3851e817c451cc36f2e6f3049db528415e3c114\nAuthor: Alex Lee <alexlee@example.com>\nDate:   Tue Jul 22 15:39:27 2014 -0400\n\n    Bug #21 - Added CSRF protection\n\ncommit 5ea51731d150f7ddc4a365437931cd8be3bf3131\nAuthor: Alex Lee <alexlee@example.com>\nDate:   Tue Jul 22 15:39:12 2014 -0400\n\n    Bug #14 - Fixed spacing on title\n\ncommit a13b85e984171c6e2a1729bb061994525f626d14\nAuthor: Aki Rose <akirose@example.com>\nDate:   Tue Jul 21 01:12:48 2014 -0400\n\n    First commit\n```\n\nLet's take note of our commit hashes for each bug (`e3851e8` for #21, `5ea5173` for #14).\n\nFirst, let's reset our main branch to the correct commit (`a13b85e`):\n\n```sh\n(main)$ git reset --hard a13b85e\nHEAD is now at a13b85e\n```\n\nNow, we can create a fresh branch for our bug #21:\n\n```sh\n(main)$ git checkout -b 21\n(21)$\n```\n\nNow, let's *cherry-pick* the commit for bug #21 on top of our branch. That means we will be applying that commit, and only that commit, directly on top of whatever our head is at.\n\n```sh\n(21)$ git cherry-pick e3851e8\n```\n\nAt this point, there is a possibility there might be conflicts. See the [**There were conflicts**](#merge-conflict) section in the [interactive rebasing section above](#interactive-rebase) for how to resolve conflicts.\n\nNow let's create a new branch for bug #14, also based on main\n\n```sh\n(21)$ git checkout main\n(main)$ git checkout -b 14\n(14)$\n```\n\nAnd finally, let's cherry-pick the commit for bug #14:\n\n```sh\n(14)$ git cherry-pick 5ea5173\n```\n\n<a name=\"delete-stale-local-branches\"></a>\n### I want to delete local branches that were deleted upstream\n\nOnce you merge a pull request on GitHub, it gives you the option to delete the merged branch in your fork. If you aren't planning to keep working on the branch, it's cleaner to delete the local copies of the branch so you don't end up cluttering up your working checkout with a lot of stale branches.\n\n```sh\n$ git fetch -p upstream\n```\n\nwhere, `upstream` is the remote you want to fetch from.\n\n<a name=\"restore-a-deleted-branch\"></a>\n### I accidentally deleted my branch\n\nIf you're regularly pushing to remote, you should be safe most of the time. But still sometimes you may end up deleting your branches. Let's say we create a branch and create a new file:\n\n```sh\n(main)$ git checkout -b my-branch\n(my-branch)$ git branch\n(my-branch)$ touch foo.txt\n(my-branch)$ ls\nREADME.md foo.txt\n```\n\nLet's add it and commit.\n\n```sh\n(my-branch)$ git add .\n(my-branch)$ git commit -m 'foo.txt added'\n(my-branch)$ foo.txt added\n 1 files changed, 1 insertions(+)\n create mode 100644 foo.txt\n(my-branch)$ git log\n\ncommit 4e3cd85a670ced7cc17a2b5d8d3d809ac88d5012\nAuthor: siemiatj <siemiatj@example.com>\nDate:   Wed Jul 30 00:34:10 2014 +0200\n\n    foo.txt added\n\ncommit 69204cdf0acbab201619d95ad8295928e7f411d5\nAuthor: Kate Hudson <katehudson@example.com>\nDate:   Tue Jul 29 13:14:46 2014 -0400\n\n    Fixes #6: Force pushing after amending commits\n```\n\nNow we're switching back to main and 'accidentally' removing our branch.\n\n```sh\n(my-branch)$ git checkout main\nSwitched to branch 'main'\nYour branch is up-to-date with 'origin/main'.\n(main)$ git branch -D my-branch\nDeleted branch my-branch (was 4e3cd85).\n(main)$ echo oh noes, deleted my branch!\noh noes, deleted my branch!\n```\n\nAt this point you should get familiar with 'reflog', an upgraded logger. It stores the history of all the action in the repo.\n\n```\n(main)$ git reflog\n69204cd HEAD@{0}: checkout: moving from my-branch to main\n4e3cd85 HEAD@{1}: commit: foo.txt added\n69204cd HEAD@{2}: checkout: moving from main to my-branch\n```\n\nAs you can see we have commit hash from our deleted branch. Let's see if we can restore our deleted branch.\n\n```sh\n(main)$ git checkout -b my-branch-help\nSwitched to a new branch 'my-branch-help'\n(my-branch-help)$ git reset --hard 4e3cd85\nHEAD is now at 4e3cd85 foo.txt added\n(my-branch-help)$ ls\nREADME.md foo.txt\n```\n\nVoila! We got our removed file back. `git reflog` is also useful when rebasing goes terribly wrong.\n\n### I want to delete a branch\n\nTo delete a remote branch:\n\n```sh\n(main)$ git push origin --delete my-branch\n```\n\nYou can also do:\n\n```sh\n(main)$ git push origin :my-branch\n```\n\nTo delete a local branch:\n\n```sh\n(main)$ git branch -d my-branch\n```\n\nTo delete a local branch that *has not* been merged to the current branch or an upstream:\n\n```sh\n(main)$ git branch -D my-branch\n```\n\n### I want to delete multiple branches\n\nSay you want to delete all branches that start with `fix/`:\n\n```sh\n(main)$ git branch | grep 'fix/' | xargs git branch -d\n```\n\n### I want to rename a branch\n\nTo rename the current (local) branch:\n\n```sh\n(main)$ git branch -m new-name\n```\n\nTo rename a different (local) branch:\n\n```sh\n(main)$ git branch -m old-name new-name\n```\n\nTo delete the `old-name` remote branch and push the `new-name` local branch:\n\n```sh\n(main)$ git push origin :old_name new_name\n```\n\n<a name=\"working-on-checkout-remote-branch\"></a>\n### I want to checkout to a remote branch that someone else is working on\n\nFirst, fetch all branches from remote:\n\n```sh\n(main)$ git fetch --all\n```\n\nSay you want to checkout to `daves` from the remote.\n\n```sh\n(main)$ git checkout --track origin/daves\nBranch daves set up to track remote branch daves from origin.\nSwitched to a new branch 'daves'\n```\n\n(`--track` is shorthand for `git checkout -b [branch] [remotename]/[branch]`)\n\nThis will give you a local copy of the branch `daves`, and any update that has been pushed will also show up remotely.\n\n### I want to create a new remote branch from current local one\n\n```sh\n$ git push <remote> HEAD\n```\n\nIf you would also like to set that remote branch as upstream for the current one, use the following instead:\n\n```sh\n$ git push -u <remote> HEAD\n```\n\nWith the `upstream` mode and the `simple` (default in Git 2.0) mode of the `push.default` config, the following command will push the current branch with regards to the remote branch that has been registered previously with `-u`:\n\n```sh\n$ git push\n```\n\nThe behavior of the other modes of `git push` is described in the [doc of `push.default`](https://git-scm.com/docs/git-config#Documentation/git-config.txt-pushdefault).\n\n### I want to set a remote branch as the upstream for a local branch\n\nYou can set a remote branch as the upstream for the current local branch using:\n\n```sh\n$ git branch --set-upstream-to [remotename]/[branch]\n# or, using the shorthand:\n$ git branch -u [remotename]/[branch]\n```\n\nTo set the upstream remote branch for another local branch:\n\n```sh\n$ git branch -u [remotename]/[branch] [local-branch]\n```\n\n<a name=\"head-to-track-remote-branch\"></a>\n### I want to set my HEAD to track the default remote branch\n\nBy checking your remote branches, you can see which remote branch your HEAD is tracking. In some cases, this is not the desired branch.\n\n```sh\n$ git branch -r\n  origin/HEAD -> origin/gh-pages\n  origin/main\n```\n\nTo change `origin/HEAD` to track `origin/main`, you can run this command:\n\n```sh\n$ git remote set-head origin --auto\norigin/HEAD set to main\n```\n\n### I made changes on the wrong branch\n\nYou've made uncommitted changes and realise you're on the wrong branch. Stash changes and apply them to the branch you want:\n\n```sh\n(wrong_branch)$ git stash\n(wrong_branch)$ git checkout <correct_branch>\n(correct_branch)$ git stash apply\n```\n\n<a name=\"split-branch-into-two\"></a>\n### I want to split a branch into two\n\nYou've made a lot of commits on a branch and now want to separate it into two, ending with a branch up to an earlier commit and another with all the changes.\n\nUse `git log` to find the commit where you want to split. Then do the following:\n\n```sh\n(original_branch)$ git checkout -b new_branch\n(new_branch)$ git checkout original_branch\n(original_branch)$ git reset --hard <sha1 split here>\n```\n\nIf you had previously pushed the `original_branch` to remote, you will need to do a force push. For more information check [Stack Overflow](https://stackoverflow.com/questions/28983458/how-to-split-a-branch-in-two-with-git/28983843#28983843)\n\n## Rebasing and Merging\n\n<a name=\"undo-rebase\"></a>\n### I want to undo rebase/merge\n\nYou may have merged or rebased your current branch with a wrong branch, or you can't figure it out or finish the rebase/merge process. Git saves the original HEAD pointer in a variable called ORIG_HEAD before doing dangerous operations, so it is simple to recover your branch at the state before the rebase/merge.\n\n```sh\n(my-branch)$ git reset --hard ORIG_HEAD\n```\n\n<a name=\"force-push-rebase\"></a>\n### I rebased, but I don't want to force push\n\nUnfortunately, you have to force push, if you want those changes to be reflected on the remote branch. This is because you have changed the history. The remote branch won't accept changes unless you force push. This is one of the main reasons many people use a merge workflow, instead of a rebasing workflow - large teams can get into trouble with developers force pushing. Use this with caution. A safer way to use rebase is not to reflect your changes on the remote branch at all, and instead to do the following:\n\n```sh\n(main)$ git checkout my-branch\n(my-branch)$ git rebase -i main\n(my-branch)$ git checkout main\n(main)$ git merge --ff-only my-branch\n```\n\nFor more, see [this SO thread](https://stackoverflow.com/questions/11058312/how-can-i-use-git-rebase-without-requiring-a-forced-push).\n\n<a name=\"interactive-rebase\"></a>\n### I need to combine commits\n\nLet's suppose you are working in a branch that is/will become a pull-request against `main`. In the simplest case when all you want to do is to combine *all* commits into a single one and you don't care about commit timestamps, you can reset and recommit. Make sure the main branch is up to date and all your changes committed, then:\n\n```sh\n(my-branch)$ git reset --soft main\n(my-branch)$ git commit -am \"New awesome feature\"\n```\n\nIf you want more control, and also to preserve timestamps, you need to do something called an interactive rebase:\n\n```sh\n(my-branch)$ git rebase -i main\n```\n\nIf you aren't working against another branch you'll have to rebase relative to your `HEAD`. If you want to squash the last 2 commits, for example, you'll have to rebase against `HEAD~2`. For the last 3, `HEAD~3`, etc.\n\n```sh\n(main)$ git rebase -i HEAD~2\n```\n\nAfter you run the interactive rebase command, you will see something like this in your  text editor:\n\n```vim\npick a9c8a1d Some refactoring\npick 01b2fd8 New awesome feature\npick b729ad5 fixup\npick e3851e8 another fix\n\n# Rebase 8074d12..b729ad5 onto 8074d12\n#\n# Commands:\n#  p, pick = use commit\n#  r, reword = use commit, but edit the commit message\n#  e, edit = use commit, but stop for amending\n#  s, squash = use commit, but meld into previous commit\n#  f, fixup = like \"squash\", but discard this commit's log message\n#  x, exec = run command (the rest of the line) using shell\n#\n# These lines can be re-ordered; they are executed from top to bottom.\n#\n# If you remove a line here THAT COMMIT WILL BE LOST.\n#\n# However, if you remove everything, the rebase will be aborted.\n#\n# Note that empty commits are commented out\n```\n\nAll the lines beginning with a `#` are comments, they won't affect your rebase.\n\nThen you replace `pick` commands with any in the list above, and you can also remove commits by removing corresponding lines.\n\nFor example, if you want to **leave the oldest (first) commit alone and combine all the following commits with the second oldest**, you should edit the letter next to each commit except the first and the second to say `f`:\n\n```vim\npick a9c8a1d Some refactoring\npick 01b2fd8 New awesome feature\nf b729ad5 fixup\nf e3851e8 another fix\n```\n\nIf you want to combine these commits **and rename the commit**, you should additionally add an `r` next to the second commit or simply use `s` instead of `f`:\n\n```vim\npick a9c8a1d Some refactoring\npick 01b2fd8 New awesome feature\ns b729ad5 fixup\ns e3851e8 another fix\n```\n\nYou can then rename the commit in the next text prompt that pops up.\n\n```vim\nNewer, awesomer features\n\n# Please enter the commit message for your changes. Lines starting\n# with '#' will be ignored, and an empty message aborts the commit.\n# rebase in progress; onto 8074d12\n# You are currently editing a commit while rebasing branch 'main' on '8074d12'.\n#\n# Changes to be committed:\n#   modified:   README.md\n#\n\n```\n\nIf everything is successful, you should see something like this:\n\n```sh\n(main)$ Successfully rebased and updated refs/heads/main.\n```\n\n#### Safe merging strategy\n`--no-commit` performs the merge but pretends the merge failed and does not autocommit, giving the user a chance to inspect and further tweak the merge result before committing. `no-ff` maintains evidence that a feature branch once existed, keeping project history consistent.\n\n```sh\n(main)$ git merge --no-ff --no-commit my-branch\n```\n\n#### I need to merge a branch into a single commit\n\n```sh\n(main)$ git merge --squash my-branch\n```\n\n<a name=\"rebase-unpushed-commits\"></a>\n#### I want to combine only unpushed commits\n\nSometimes you have several work in progress commits that you want to combine before you push them upstream. You don't want to accidentally combine any commits that have already been pushed upstream because someone else may have already made commits that reference them.\n\n```sh\n(main)$ git rebase -i @{u}\n```\n\nThis will do an interactive rebase that lists only the commits that you haven't already pushed, so it will be safe to reorder/fix/squash anything in the list.\n\n#### I need to abort the merge\n\nSometimes the merge can produce problems in certain files, in those cases we can use the option `abort` to abort the current conflict resolution process, and try to reconstruct the pre-merge state.\n\n```sh\n(my-branch)$ git merge --abort\n```\n\nThis command is available since Git version >= 1.7.4\n\n### I need to update the parent commit of my branch\n\nSay I have a main branch, a feature-1 branch branched from main, and a feature-2 branch branched off of feature-1. If I make a commit to feature-1, then the parent commit of feature-2 is no longer accurate (it should be the head of feature-1, since we branched off of it). We can fix this with `git rebase --onto`.\n\n```sh\n(feature-2)$ git rebase --onto feature-1 <the first commit in your feature-2 branch that you don't want to bring along> feature-2\n```\n\nThis helps in sticky scenarios where you might have a feature built on another feature that hasn't been merged yet, and a bugfix on the feature-1 branch needs to be reflected in your feature-2 branch.\n\n### Check if all commits on a branch are merged\n\nTo check if all commits on a branch are merged into another branch, you should diff between the heads (or any commits) of those branches:\n\n```sh\n(main)$ git log --graph --left-right --cherry-pick --oneline HEAD...feature/120-on-scroll\n```\n\nThis will tell you if any commits are in one but not the other, and will give you a list of any nonshared between the branches. Another option is to do this:\n\n```sh\n(main)$ git log main ^feature/120-on-scroll --no-merges\n```\n\n### Possible issues with interactive rebases\n\n<a name=\"noop\"></a>\n#### The rebase editing screen says 'noop'\n\nIf you're seeing this:\n```\nnoop\n```\n\nThat means you are trying to rebase against a branch that is at an identical commit, or is *ahead* of your current branch. You can try:\n\n* making sure your main branch is where it should be\n* rebase against `HEAD~2` or earlier instead\n\n<a name=\"merge-conflict\"></a>\n#### There were conflicts\n\nIf you are unable to successfully complete the rebase, you may have to resolve conflicts.\n\nFirst run `git status` to see which files have conflicts in them:\n\n```sh\n(my-branch)$ git status\nOn branch my-branch\nChanges not staged for commit:\n  (use \"git add <file>...\" to update what will be committed)\n  (use \"git checkout -- <file>...\" to discard changes in working directory)\n\n  both modified:   README.md\n```\n\nIn this example, `README.md` has conflicts. Open that file and look for the following:\n\n```vim\n   <<<<<<< HEAD\n   some code\n   =========\n   some code\n   >>>>>>> new-commit\n```\n\nYou will need to resolve the differences between the code that was added in your new commit (in the example, everything from the middle line to `new-commit`) and your `HEAD`.\n\nIf you want to keep one branch's version of the code, you can use `--ours` or `--theirs`:\n\n```sh\n(main*)$ git checkout --ours README.md\n```\n\n- When *merging*, use `--ours` to keep changes from the local branch, or `--theirs` to keep changes from the other branch.\n- When *rebasing*, use `--theirs` to keep changes from the local branch, or `--ours` to keep changes from the other branch. For an explanation of this swap, see [this note in the Git documentation](https://git-scm.com/docs/git-rebase#Documentation/git-rebase.txt---merge).\n\nIf the merges are more complicated, you can use a visual diff editor:\n\n```sh\n(main*)$ git mergetool -t opendiff\n```\n\nAfter you have resolved all conflicts and tested your code, `git add` the files you have changed, and then continue the rebase with `git rebase --continue`\n\n```sh\n(my-branch)$ git add README.md\n(my-branch)$ git rebase --continue\n```\n\nIf after resolving all the conflicts you end up with an identical tree to what it was before the commit, you need to `git rebase --skip` instead.\n\nIf at any time you want to stop the entire rebase and go back to the original state of your branch, you can do so:\n\n```sh\n(my-branch)$ git rebase --abort\n```\n\n<a name=\"stashing\"></a>\n## Stash\n\n### Stash all edits\n\nTo stash all the edits in your working directory\n\n```sh\n$ git stash\n```\n\nIf you also want to stash untracked files, use `-u` option.\n\n```sh\n$ git stash -u\n```\n\n### Stash specific files\n\nTo stash only one file from your working directory\n\n```sh\n$ git stash push working-directory-path/filename.ext\n```\n\nTo stash multiple files from your working directory\n\n```sh\n$ git stash push working-directory-path/filename1.ext working-directory-path/filename2.ext\n```\n\n<a name=\"stash-msg\"></a>\n### Stash with message\n\n```sh\n$ git stash save <message>\n```\n\nor\n\n```sh\n$ git stash push -m <message>\n```\n\n<a name=\"stash-apply-specific\"></a>\n### Apply a specific stash from list\n\nFirst check your list of stashes with message using\n\n```sh\n$ git stash list\n```\n\nThen apply a specific stash from the list using\n\n```sh\n$ git stash apply \"stash@{n}\"\n```\n\nHere, 'n' indicates the position of the stash in the stack. The topmost stash will be position 0.\n\nFurthermore, using a time-based stash reference is also possible.\n\n```sh\n$ git stash apply \"stash@{2.hours.ago}\"\n```\n\n<a name=\"stage-and-keep-unstaged\"></a>\n### Stash while keeping unstaged edits\n\nYou can manually create a `stash commit`, and then use `git stash store`.\n\n```sh\n$ git stash create\n$ git stash store -m <message> CREATED_SHA1\n```\n\n## Finding\n\n### I want to find a string in any commit\n\nTo find a certain string which was introduced in any commit, you can use the following structure:\n\n```sh\n$ git log -S \"string to find\"\n```\n\nCommons parameters:\n\n* `--source` means to show the ref name given on the command line by which each commit was reached.\n\n* `--all` means to start from every branch.\n\n* `--reverse` prints in reverse order, it means that will show the first commit that made the change.\n\n<a name=\"find-by-committer\"></a>\n### I want to find by author/committer\n\nTo find all commits by author/committer you can use:\n\n```sh\n$ git log --author=<name or email>\n$ git log --committer=<name or email>\n```\n\nKeep in mind that author and committer are not the same. The `--author` is the person who originally wrote the code; on the other hand, the `--committer`, is the person who committed the code on behalf of the original author.\n\n### I want to list commits containing specific files\n\nTo find all commits containing a specific file you can use:\n\n```sh\n$ git log -- <path to file>\n```\n\nYou would usually specify an exact path, but you may also use wild cards in the path and file name:\n\n```sh\n$ git log -- **/*.js\n```\n\nWhile using wildcards, it's useful to inform `--name-status` to see the list of committed files:\n\n```sh\n$ git log --name-status -- **/*.js\n```\n\n<a name=\"view-commit-history-for-specific-function\"></a>\n### I want to view the commit history for a specific function\n\nTo trace the evolution of a single function you can use:\n\n```sh\n$ git log -L :FunctionName:FilePath\n```\n\nNote that you can combine this with further `git log` options, like [revision ranges](https://git-scm.com/docs/gitrevisions) and [commit limits](https://git-scm.com/docs/git-log/#_commit_limiting).\n\n### Find a tag where a commit is referenced\n\nTo find all tags containing a specific commit:\n\n```sh\n$ git tag --contains <commitid>\n```\n\n## Submodules\n\n<a name=\"clone-submodules\"></a>\n### Clone all submodules\n\n```sh\n$ git clone --recursive git://github.com/foo/bar.git\n```\n\nIf already cloned:\n\n```sh\n$ git submodule update --init --recursive\n```\n\n<a name=\"delete-submodule\"></a>\n### Remove a submodule\n\nCreating a submodule is pretty straight-forward, but deleting them less so. The commands you need are:\n\n```sh\n$ git submodule deinit submodulename\n$ git rm submodulename\n$ git rm --cached submodulename\n$ rm -rf .git/modules/submodulename\n```\n\n## Miscellaneous Objects\n\n### Copy a folder or file from one branch to another\n\n```sh\n$ git checkout <branch-you-want-the-directory-from> -- <folder-name or file-name>\n```\n\n### Restore a deleted file\n\nFirst find the commit when the file last existed:\n\n```sh\n$ git rev-list -n 1 HEAD -- filename\n```\n\nThen checkout that file:\n\n```\ngit checkout deletingcommitid^ -- filename\n```\n\n### Delete tag\n\n```sh\n$ git tag -d <tag_name>\n$ git push <remote> :refs/tags/<tag_name>\n```\n\n<a name=\"recover-tag\"></a>\n### Recover a deleted tag\n\nIf you want to recover a tag that was already deleted, you can do so by following these steps: First, you need to find the unreachable tag:\n\n```sh\n$ git fsck --unreachable | grep tag\n```\n\nMake a note of the tag's hash. Then, restore the deleted tag with following, making use of [`git update-ref`](https://git-scm.com/docs/git-update-ref):\n\n```sh\n$ git update-ref refs/tags/<tag_name> <hash>\n```\n\nYour tag should now have been restored.\n\n### Deleted Patch\n\nIf someone has sent you a pull request on GitHub, but then deleted their original fork, you will be unable to clone their repository or to use `git am` as the [.diff, .patch](https://github.com/blog/967-github-secrets) URLs become unavailable. But you can checkout the PR itself using [GitHub's special refs](https://gist.github.com/piscisaureus/3342247). To fetch the content of PR#1 into a new branch called pr_1:\n\n```sh\n$ git fetch origin refs/pull/1/head:pr_1\nFrom github.com:foo/bar\n * [new ref]         refs/pull/1/head -> pr_1\n```\n\n### Exporting a repository as a Zip file\n\n```sh\n$ git archive --format zip --output /full/path/to/zipfile.zip main\n```\n### Push a branch and a tag that have the same name\n\nIf there is a tag on a remote repository that has the same name as a branch you will get the following error when trying to push that branch with a standard `$ git push <remote> <branch>` command.\n\n```sh\n$ git push origin <branch>\nerror: dst refspec same matches more than one.\nerror: failed to push some refs to '<git server>'\n```\n\nFix this by specifying you want to push the head reference.\n\n```sh\n$ git push origin refs/heads/<branch-name>\n```\n\nIf you want to push a tag to a remote repository that has the same name as a branch, you can use a similar command.\n\n```sh\n$ git push origin refs/tags/<tag-name>\n```\n\n## Tracking Files\n\n<a name=\"change-file-name-capitalization-without-changing-contents\"></a>\n### I want to change a file name's capitalization, without changing the contents of the file\n\n```sh\n(main)$ git mv --force myfile MyFile\n```\n\n### I want to overwrite local files when doing a git pull\n\n```sh\n(main)$ git fetch --all\n(main)$ git reset --hard origin/main\n```\n\n<a name=\"remove-from-git\"></a>\n### I want to remove a file from Git but keep the file\n\n```sh\n(main)$ git rm --cached log.txt\n```\n\n### I want to revert a file to a specific revision\n\nAssuming the hash of the commit you want is c5f567:\n\n```sh\n(main)$ git checkout c5f567 -- file1/to/restore file2/to/restore\n```\n\nIf you want to revert to changes made just 1 commit before c5f567, pass the commit hash as c5f567~1:\n\n```sh\n(main)$ git checkout c5f567~1 -- file1/to/restore file2/to/restore\n```\n\n### I want to list changes of a specific file between commits or branches\n\nAssuming you want to compare last commit with file from commit c5f567:\n\n```sh\n$ git diff HEAD:path_to_file/file c5f567:path_to_file/file\n# or\n$ git diff HEAD c5f567 -- path_to_file/file\n```\n\nIf you are going to compare changes between the tips of the `main` and the `staging` branches:\n\n```sh\n$ git diff main:path_to_file/file staging:path_to_file/file\n# or\n$ git diff main staging -- path_to_file/file\n```\n\n### I want Git to ignore changes to a specific file\n\nThis works great for config templates or other files that require locally adding credentials that shouldn't be committed.\n\n```sh\n$ git update-index --assume-unchanged file-to-ignore\n```\n\nNote that this does *not* remove the file from source control - it is only ignored locally. To undo this and tell Git to notice changes again, this clears the ignore flag:\n\n```sh\n$ git update-index --no-assume-unchanged file-to-stop-ignoring\n```\n\n## Debugging with Git\n\nThe [git-bisect](https://git-scm.com/docs/git-bisect) command uses a binary search to find which commit in your Git history introduced a bug.\n\nSuppose you're on the `main` branch, and you want to find the commit that broke some feature. You start bisect:\n\n```sh\n$ git bisect start\n```\n\nThen you should specify which commit is bad, and which one is known to be good. Assuming that your *current* version is bad, and `v1.1.1` is good:\n\n```sh\n$ git bisect bad\n$ git bisect good v1.1.1\n```\n\nNow `git-bisect` selects a commit in the middle of the range that you specified, checks it out, and asks you whether it's good or bad. You should see something like:\n\n```sh\n$ Bisecting: 5 revision left to test after this (roughly 5 step)\n$ [c44abbbee29cb93d8499283101fe7c8d9d97f0fe] Commit message\n$ (c44abbb)$\n```\n\nYou will now check if this commit is good or bad. If it's good:\n\n```sh\n$ (c44abbb)$ git bisect good\n```\n\nand `git-bisect` will select another commit from the range for you. This process (selecting `good` or `bad`) will repeat until there are no more revisions left to inspect, and the command will finally print a description of the **first** bad commit.\n\n## Configuration\n\n### I want to add aliases for some Git commands\n\nOn OS X and Linux, your git configuration file is stored in ```~/.gitconfig```.  I've added some example aliases I use as shortcuts (and some of my common typos) in the ```[alias]``` section as shown below:\n\n```vim\n[alias]\n    a = add\n    amend = commit --amend\n    c = commit\n    ca = commit --amend\n    ci = commit -a\n    co = checkout\n    d = diff\n    dc = diff --changed\n    ds = diff --staged\n    extend = commit --amend -C HEAD\n    f = fetch\n    loll = log --graph --decorate --pretty=oneline --abbrev-commit\n    m = merge\n    one = log --pretty=oneline\n    outstanding = rebase -i @{u}\n    reword = commit --amend --only\n    s = status\n    unpushed = log @{u}\n    wc = whatchanged\n    wip = rebase -i @{u}\n    zap = fetch -p\n    day = log --reverse --no-merges --branches=* --date=local --since=midnight --author=\\\"$(git config --get user.name)\\\"\n    delete-merged-branches = \"!f() { git checkout --quiet main && git branch --merged | grep --invert-match '\\\\*' | xargs -n 1 git branch --delete; git checkout --quiet @{-1}; }; f\"\n```\n\n### I want to add an empty directory to my repository\n\nYou can’t! Git doesn’t support this, but there’s a hack. You can create a .gitignore file in the directory with the following contents:\n\n```\n # Ignore everything in this directory\n *\n # Except this file\n !.gitignore\n```\n\nAnother common convention is to make an empty file in the folder, titled .gitkeep.\n\n```sh\n$ mkdir mydir\n$ touch mydir/.gitkeep\n```\n\nYou can also name the file as just .keep , in which case the second line above would be ```touch mydir/.keep```\n\n### I want to cache a username and password for a repository\n\nYou might have a repository that requires authentication.  In which case you can cache a username and password so you don't have to enter it on every push and pull. Credential helper can do this for you.\n\n```sh\n$ git config --global credential.helper cache\n# Set git to use the credential memory cache\n```\n\n```sh\n$ git config --global credential.helper 'cache --timeout=3600'\n# Set the cache to timeout after 1 hour (setting is in seconds)\n```\n\nTo find a credential helper:\n\n```sh\n$ git help -a | grep credential\n# Shows you possible credential helpers\n```\n\nFor OS specific credential caching:\n\n```sh\n$ git config --global credential.helper osxkeychain\n# For OSX\n```\n\n```sh\n$ git config --global credential.helper manager\n# Git for Windows 2.7.3+\n```\n\n```sh\n$ git config --global credential.helper gnome-keyring\n# Ubuntu and other GNOME-based distros\n```\n\nMore credential helpers can likely be found for different distributions and operating systems.\n\n### I want to make Git ignore permissions and filemode changes\n\n```sh\n$ git config core.fileMode false\n```\n\nIf you want to make this the default behaviour for logged-in users, then use:\n\n```sh\n$ git config --global core.fileMode false\n```\n\n### I want to set a global user\n\nTo configure user information used across all local repositories, and to set a name that is identifiable for credit when review version history:\n\n```sh\n$ git config --global user.name “[firstname lastname]”\n```\n\nTo set an email address that will be associated with each history marker:\n\n```sh\ngit config --global user.email “[valid-email]”\n```\n\n## I've no idea what I did wrong\n\nSo, you're screwed - you `reset` something, or you merged the wrong branch, or you force pushed and now you can't find your commits. You know, at some point, you were doing alright, and you want to go back to some state you were at.\n\nThis is what `git reflog` is for. `reflog` keeps track of any changes to the tip of a branch, even if that tip isn't referenced by a branch or a tag. Basically, every time HEAD changes, a new entry is added to the reflog. This only works for local repositories, sadly, and it only tracks movements (not changes to a file that weren't recorded anywhere, for instance).\n\n```sh\n(main)$ git reflog\n0a2e358 HEAD@{0}: reset: moving to HEAD~2\n0254ea7 HEAD@{1}: checkout: moving from 2.2 to main\nc10f740 HEAD@{2}: checkout: moving from main to 2.2\n```\n\nThe reflog above shows a checkout from main to the 2.2 branch and back. From there, there's a hard reset to an older commit. The latest activity is represented at the top labeled `HEAD@{0}`.\n\nIf it turns out that you accidentally moved back, the reflog will contain the commit main pointed to (0254ea7) before you accidentally dropped 2 commits.\n\n```sh\n$ git reset --hard 0254ea7\n```\n\nUsing `git reset` it is then possible to change main back to the commit it was before. This provides a safety net in case history was accidentally changed.\n\n(copied and edited from [Source](https://www.atlassian.com/git/tutorials/rewriting-history/git-reflog)).\n\n<a name=\"git-shortcuts\"></a>\n## Git Shortcuts\n\n### Git Bash\n\nOnce you're comfortable with what the above commands are doing, you might want to create some shortcuts for Git Bash. This allows you to work a lot faster by doing complex tasks in really short commands.\n\n```sh\nalias sq=squash\n\nfunction squash() {\n    git rebase -i HEAD~$1\n}\n```\n\nCopy those commands to your .bashrc or .bash_profile.\n\n### PowerShell on Windows\n\nIf you are using PowerShell on Windows, you can also set up aliases and functions. Add these commands to your profile, whose path is defined in the `$profile` variable. Learn more at the [About Profiles](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_profiles) page on the Microsoft documentation site.\n\n```powershell\nSet-Alias sq Squash-Commits\n\nfunction Squash-Commits {\n  git rebase -i HEAD~$1\n}\n```\n\n# Other Resources\n\n## Books\n\n* [Learn Enough Git to Be Dangerous](https://www.learnenough.com/git-tutorial) - A book by Michael Hartl covering Git from basics\n* [Pro Git](https://git-scm.com/book/en/v2) - Scott Chacon and Ben Straub's excellent book about Git\n* [Git Internals](https://github.com/pluralsight/git-internals-pdf) - Scott Chacon's other excellent book about Git\n* [Nasa handbook](https://www.nasa.gov/wp-content/uploads/2018/09/nasa_systems_engineering_handbook_0.pdf)\n\n## Tutorials\n\n* [19 Git Tips For Everyday Use](https://www.alexkras.com/19-git-tips-for-everyday-use) - A list of useful Git one liners\n* [Atlassian's Git tutorial](https://www.atlassian.com/git/tutorials) Get Git right with tutorials from beginner to advanced.\n* [Getting solid at Git rebase vs. merge](https://medium.com/@porteneuve/getting-solid-at-git-rebase-vs-merge-4fa1a48c53aa)\n* [Git and GitHub Cartoons](https://allisonhorst.com/git-github) – Cartoons by Allison Horst that showcase how to use Git.\n* [Git Commands and Best Practices Cheat Sheet](https://zeroturnaround.com/rebellabs/git-commands-and-best-practices-cheat-sheet) - A Git cheat sheet in a blog post with more explanations\n* [Git from the inside out](https://codewords.recurse.com/issues/two/git-from-the-inside-out) - A tutorial that dives into Git's internals\n* [git-workflow](https://github.com/asmeurer/git-workflow) - [Aaron Meurer](https://github.com/asmeurer)'s howto on using Git to contribute to open source repositories\n* [GitHub as a workflow](https://hugogiraudel.com/2015/08/13/github-as-a-workflow/) - An interesting take on using GitHub as a workflow, particularly with empty PRs\n* [Githug](https://github.com/Gazler/githug) - A game to learn more common Git workflows\n* [Learn Git branching](https://learngitbranching.js.org/) An interactive web based branching/merging/rebasing tutorial\n* [learnGitBranching](https://github.com/pcottle/learnGitBranching) - An interactive git visualization to challenge and educate!\n\n## Scripts and Tools\n\n* [firstaidgit.io](http://firstaidgit.io/) A searchable selection of the most frequently asked Git questions\n* [git-extra-commands](https://github.com/unixorn/git-extra-commands) - a collection of useful extra Git scripts\n* [git-extras](https://github.com/tj/git-extras) - GIT utilities -- repo summary, repl, changelog population, author commit percentages and more\n* [git-fire](https://github.com/qw3rtman/git-fire) - git-fire is a Git plugin that helps in the event of an emergency by adding all current files, committing, and pushing to a new branch (to prevent merge conflicts).\n* [git-tips](https://github.com/git-tips/tips) - Small Git tips\n* [git-town](https://github.com/Originate/git-town) - Generic, high-level Git workflow support! http://www.git-town.com\n\n## GUI Clients\n* [GitKraken](https://www.gitkraken.com/) - The downright luxurious Git client, for Windows, Mac & Linux\n* [git-cola](https://git-cola.github.io/) - another Git client for Windows and OS X\n* [GitUp](https://github.com/git-up/GitUp) - A newish GUI that has some very opinionated ways of dealing with Git's complications\n* [gitx-dev](https://rowanj.github.io/gitx/) - another graphical Git client for OS X\n* [Sourcetree](https://www.sourcetreeapp.com/) - Simplicity meets power in a beautiful and free Git GUI. For Windows and Mac.\n* [Tower](https://www.git-tower.com/) - graphical Git client for OS X (paid)\n* [tig](https://jonas.github.io/tig/) - terminal text-mode interface for Git\n* [Magit](https://magit.vc/) - Interface to Git implemented as an Emacs package.\n* [GitExtensions](https://github.com/gitextensions/gitextensions) - a shell extension, a Visual Studio 2010-2015 plugin and a standalone Git repository tool.\n* [Fork](https://git-fork.com/) - a fast and friendly Git client for Mac (beta)\n* [gmaster](https://gmaster.io/) - a Git client for Windows that has 3-way merge, analyze refactors, semantic diff and merge (beta)\n* [gitk](https://git-scm.com/docs/gitk) - a Git client for linux to allow simple view of repo state.\n* [SublimeMerge](https://www.sublimemerge.com/) - Blazing fast, extensible client that provides 3-way merges, powerful search and syntax highlighting, in active development.\n"
  },
  {
    "path": "README_es.md",
    "content": "# Reglas de vuelo para git\n\n🌍\n*[English](README.md) ∙ [Español](README_es.md)  ∙  [Русский](README_ru.md) ∙ [繁體中文](README_zh-TW.md) ∙ [简体中文](README_zh-CN.md) ∙ [한국어](README_kr.md)  ∙  [Tiếng Việt](README_vi.md) ∙ [Français](README_fr.md) ∙ [日本語](README_ja.md)*\n\n#### ¿Qué son \"reglas de vuelo\"?\n\nUna guía para astronautas (ahora, programadores usando git) acerca de qué hacer cuando las cosas van mal.\n\n>  *Las reglas de vuelo* son los conocimientos adquiridos con tanto esfuerzo en manuales que enumeran, paso a paso, qué hacer si ocurre X y por qué. Básicamente, son procedimientos operativos extremadamente detallados y específicos de cada escenario. [...]\n\n> La NASA ha estado capturando nuestros errores, desastres y soluciones desde principios de la década de 1960, cuando los equipos de tierra de la era Mercurio comenzaron a recopilar \"lecciones aprendidas\" en un compendio que ahora enumera miles de situaciones problemáticas, desde fallas en el motor hasta fallas reventadas en computadoras, y sus soluciones.\n\n&mdash; Chris Hadfield, *An Astronaut's Guide to Life*.\n\n#### Convenciones para este documento\n\nEn aras de la claridad, todos los ejemplos de este documento usan un indicador de bash personalizado para señalar la rama actual y si hay cambios escalonados o no. La rama se incluye entre paréntesis, y un `*` al lado del nombre de la rama indica cambios realizados.\n\n[![Únete al chat en  https://gitter.im/k88hudson/git-flight-rules](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/k88hudson/git-flight-rules?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n\n<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n  - [Repositorios](#repositorios)\n    - [Quiero empezar un repositorio local](#quiero-empezar-un-repositorio-local)\n    - [Quiero clonar un repositorio remoto](#quiero-clonar-un-repositorio-remoto)\n  - [Editando commits](#editando-commits)\n    - [¿Qué acabo de hacer en el commit?](#%C2%BFqu%C3%A9-acabo-de-hacer-en-el-commit)\n    - [Escribí algo mal en el mensaje del commit](#escrib%C3%AD-algo-mal-en-el-mensaje-del-commit)\n    - [Hice un commit con el nombre y correo mal configurado](#hice-un-commit-con-el-nombre-y-correo-mal-configurado)\n    - [Quiero remover un archivo de un commit](#quiero-remover-un-archivo-de-un-commit)\n    - [Quiero borrar o remover mi último commit](#quiero-borrar-o-remover-mi-%C3%BAltimo-commit)\n    - [Eliminar/remover commit arbitrario](#eliminarremover-commit-arbitrario)\n    - [Intenté subir mi commit enmendado al repositorio remoto, pero obtuve un mensaje de error](#intent%C3%A9-subir-mi-commit-enmendado-al-repositorio-remoto-pero-obtuve-un-mensaje-de-error)\n    - [Accidentalmente hice un hard reset y quiero mis cambios de vuelta](#accidentalmente-hice-un-hard-reset-y-quiero-mis-cambios-de-vuelta)\n    - [Accidentalment hice un commit y empujé una fusión](#accidentalment-hice-un-commit-y-empuj%C3%A9-una-fusi%C3%B3n)\n    - [Accidentalmente hice un commit y empujé archivos que contienen data sensible](#accidentalmente-hice-un-commit-y-empuj%C3%A9-archivos-que-contienen-data-sensible)\n  - [Staging](#staging)\n    - [Necesito agregar otros cambios al commit anterior](#necesito-agregar-otros-cambios-al-commit-anterior)\n    - [Quiero agregar parte de un nuevo archivo, pero no todo el archivo](#quiero-agregar-parte-de-un-nuevo-archivo-pero-no-todo-el-archivo)\n    - [Quiero agregar cambios en un archivo a dos commits diferentes](#quiero-agregar-cambios-en-un-archivo-a-dos-commits-diferentes)\n    - [Quiero crear mis ediciones sin escalonar y eliminar mis ediciones escalonadas](#quiero-crear-mis-ediciones-sin-escalonar-y-eliminar-mis-ediciones-escalonadas)\n  - [Ediciones sin escena](#ediciones-sin-escena)\n    - [Deseo mover mis ediciones sin escena a una nueva rama](#deseo-mover-mis-ediciones-sin-escena-a-una-nueva-rama)\n    - [Deseo mover mis ediciones sin escena a una rama diferente existente](#deseo-mover-mis-ediciones-sin-escena-a-una-rama-diferente-existente)\n    - [Quiero descartar mis cambios locales no confirmados (en escena y sin escena)](#quiero-descartar-mis-cambios-locales-no-confirmados-en-escena-y-sin-escena)\n    - [Quiero descartar cambios específicos no planificados](#quiero-descartar-cambios-espec%C3%ADficos-no-planificados)\n    - [Quiero descartar archivos específicos no escaneados](#quiero-descartar-archivos-espec%C3%ADficos-no-escaneados)\n    - [Deseo descartar solo mis cambios locales sin escenario](#deseo-descartar-solo-mis-cambios-locales-sin-escenario)\n    - [Quiero descartar todos mis archivos sin seguimiento](#quiero-descartar-todos-mis-archivos-sin-seguimiento)\n  - [Ramas](#ramas)\n    - [Quiero enumerar todas las ramas](#quiero-enumerar-todas-las-ramas)\n    - [Crear una rama desde una confirmación](#crear-una-rama-desde-una-confirmaci%C3%B3n)\n    - [Hice pull de / en la rama incorrecta](#hice-pull-de--en-la-rama-incorrecta)\n    - [Quiero descartar confirmaciones locales para que mi rama sea la misma que la del servidor](#quiero-descartar-confirmaciones-locales-para-que-mi-rama-sea-la-misma-que-la-del-servidor)\n    - [Hice commit a main en lugar de una nueva rama](#hice-commit-a-main-en-lugar-de-una-nueva-rama)\n    - [Quiero mantener todo el archivo de otro ref-ish](#quiero-mantener-todo-el-archivo-de-otro-ref-ish)\n    - [Realicé varios commits en una sola rama que debería estar en diferentes ramas](#realic%C3%A9-varios-commits-en-una-sola-rama-que-deber%C3%ADa-estar-en-diferentes-ramas)\n    - [Quiero eliminar las ramas locales que se eliminaron en sentido ascendente](#quiero-eliminar-las-ramas-locales-que-se-eliminaron-en-sentido-ascendente)\n    - [Accidentalmente borré mi rama](#accidentalmente-borr%C3%A9-mi-rama)\n    - [Quiero eliminar una rama](#quiero-eliminar-una-rama)\n    - [Quiero eliminar varias ramas](#quiero-eliminar-varias-ramas)\n    - [Quiero cambiar el nombre de una rama](#quiero-cambiar-el-nombre-de-una-rama)\n    - [Quiero hacer checkout en una rama remota en la que alguien más está trabajando](#quiero-hacer-checkout-en-una-rama-remota-en-la-que-alguien-m%C3%A1s-est%C3%A1-trabajando)\n    - [Quiero crear una nueva rama remota desde la actual local](#quiero-crear-una-nueva-rama-remota-desde-la-actual-local)\n    - [Quiero configurar una rama remota como upstream para una rama local](#quiero-configurar-una-rama-remota-como-upstream-para-una-rama-local)\n    - [Quiero configurar mi HEAD para rastrear la rama remota predeterminada](#quiero-configurar-mi-head-para-rastrear-la-rama-remota-predeterminada)\n  - [Rebasing y Merging](#rebasing-y-merging)\n    - [Quiero deshacer rebase/merge](#quiero-deshacer-rebasemerge)\n    - [Hice rebase, pero no quiero forzar el push](#hice-rebase-pero-no-quiero-forzar-el-push)\n    - [Necesito combinar commits](#necesito-combinar-commits)\n      - [Estrategia de merge segura](#estrategia-de-merge-segura)\n      - [Necesito fusionar una rama en un solo commit](#necesito-fusionar-una-rama-en-un-solo-commit)\n      - [Quiero combinar solo los commits sin haber hecho push](#quiero-combinar-solo-los-commits-sin-haber-hecho-push)\n      - [Necesito abortar el merge](#necesito-abortar-el-merge)\n    - [Comprobar si se combinan todos los commits de un branch](#comprobar-si-se-combinan-todos-los-commits-de-un-branch)\n    - [Posibles problemas con rebase interactivos](#posibles-problemas-con-rebase-interactivos)\n      - [La pantalla de edición de rebase dice 'noop'](#la-pantalla-de-edici%C3%B3n-de-rebase-dice-noop)\n      - [Hubo conflictos](#hubo-conflictos)\n  - [Stash](#stash)\n    - [Usar stash en todos los cambios](#usar-stash-en-todos-los-cambios)\n    - [Usar stash para archivos específicos](#usar-stash-para-archivos-espec%C3%ADficos)\n    - [Usar stash con un mensaje](#usar-stash-con-un-mensaje)\n    - [Aplicar un stash específico de la lista](#aplicar-un-stash-espec%C3%ADfico-de-la-lista)\n  - [Búsqueda](#b%C3%BAsqueda)\n    - [Quiero encontra un string en algún commit](#quiero-encontra-un-string-en-alg%C3%BAn-commit)\n    - [Quiero buscar por autor / committer](#quiero-buscar-por-autor--committer)\n    - [Quiero enumerar commits que contienen archivos específicos](#quiero-enumerar-commits-que-contienen-archivos-espec%C3%ADficos)\n    - [Encontrar una etiqueta donde se hace referencia a un commit](#encontrar-una-etiqueta-donde-se-hace-referencia-a-un-commit)\n  - [Submódulos](#subm%C3%B3dulos)\n    - [Clonar todos los submódulos](#clonar-todos-los-subm%C3%B3dulos)\n    - [Remover un submódulo](#remover-un-subm%C3%B3dulo)\n  - [Objetos diversos](#objetos-diversos)\n    - [Restaurar un archivo eliminado](#restaurar-un-archivo-eliminado)\n    - [Eliminar una etiqueta](#eliminar-una-etiqueta)\n    - [Recuperar una etiqueta eliminada](#recuperar-una-etiqueta-eliminada)\n    - [Patch eliminado](#patch-eliminado)\n    - [Exportar un repositorio como un archivo Zip](#exportar-un-repositorio-como-un-archivo-zip)\n  - [Seguimiento de archivos](#seguimiento-de-archivos)\n    - [Quiero cambiar el uso de mayúsculas de un nombre de archivo, sin cambiar el contenido del archivo](#quiero-cambiar-el-uso-de-may%C3%BAsculas-de-un-nombre-de-archivo-sin-cambiar-el-contenido-del-archivo)\n    - [Quiero sobrescribir los archivos locales cuando hago un git pull](#quiero-sobrescribir-los-archivos-locales-cuando-hago-un-git-pull)\n    - [Quiero eliminar un archivo de Git pero mantener el archivo](#quiero-eliminar-un-archivo-de-git-pero-mantener-el-archivo)\n    - [Quiero revertir un archivo a una revisión específica](#quiero-revertir-un-archivo-a-una-revisi%C3%B3n-espec%C3%ADfica)\n  - [Configuración](#configuraci%C3%B3n)\n    - [Quiero agregar alias para algunos comandos de Git](#quiero-agregar-alias-para-algunos-comandos-de-git)\n    - [Quiero agregar un directorio vacío a mi repositorio](#quiero-agregar-un-directorio-vac%C3%ADo-a-mi-repositorio)\n    - [Quiero guardar en caché un nombre de usuario y contraseña para un repositorio](#quiero-guardar-en-cach%C3%A9-un-nombre-de-usuario-y-contrase%C3%B1a-para-un-repositorio)\n    - [Quiero hacer que Git ignore los permisos y cambios en el modo de archivo](#quiero-hacer-que-git-ignore-los-permisos-y-cambios-en-el-modo-de-archivo)\n  - [No tengo idea de lo que hice mal](#no-tengo-idea-de-lo-que-hice-mal)\n- [Otros recursos](#otros-recursos)\n  - [Libros](#libros)\n  - [Tutoriales](#tutoriales)\n  - [Scripts y herramientas](#scripts-y-herramientas)\n  - [Clientes GUI](#clientes-gui)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n## Repositorios\n\n### Quiero empezar un repositorio local\n\nPara inicializar un directorio existente como un repositorio de Git:\n\n```sh\n(my-folder) $ git init\n```\n\n### Quiero clonar un repositorio remoto\n\nPara clonar (copiar) un repositorio remoto, copia la url del repositorio y ejecuta:\n\n```sh\n$ git clone [url]\n```\n\n## Editando commits\n\n### ¿Qué acabo de hacer en el commit?\n\nDigamos que simplemente hiciste cambios a ciegas con `git commit -a` y no estás seguro de cuál fue el contenido real de la confirmación que acabas de realizar. Puedes mostrar el último commit en su HEAD actual con:\n\n```sh\n(main)$ git show\n```\n\no\n\n```sh\n$ git log -n1 -p\n```\n\n### Escribí algo mal en el mensaje del commit\n\nSi escribiste algo mal y todavía no has subido tu commit, puedes hacer lo siguiente para cambiar el mensaje del commit:\n\n```sh\n$ git commit --amend --only\n```\nEsto abrirá tu editor de texto por defecto, donde puedes editar el mensaje. Por otro lado, tú puedes hacer todo esto con un solo comando:\n\n```sh\n$ git commit --amend --only -m 'xxxxxxx'\n```\n\nSi ya has subido tu commit, puedes corregirlo usando amend y luego forzar el push, pero esto no es recomendado.\n\n### Hice un commit con el nombre y correo mal configurado\n\nSi es un solo commit, corrígelo\n\n```sh\n$ git commit --amend --author \"Nuevo autor <authoremail@mydomain.com>\"\n```\n\nSi necesitas cambiar todo el historial, mira la página 'git filter-branch' del manual\n\n\n### Quiero remover un archivo de un commit\n\nPara remover un archivo de un commit, haz lo siguiente:\n\n```sh\n$ git checkout HEAD^ miArchivo\n$ git add -A\n$ git commit --amend\n```\n\nEsto es particularmente útil cuando tienes un patch abierto y has hecho commit de un archivo innecesario, necesitar forzar el push para actualizar el parche en un control remoto.\n\n### Quiero borrar o remover mi último commit\n\nSi necesitas eliminar commits, puedes usar lo siguiente. Sin embargo, cambiará irreversiblemente su historial y arruinará la historia de cualquier otra persona que ya haya clonado el repositorio. En resumen, si no estás seguro, nunca deberías hacer esto, nunca.\n\n```sh\n$ git reset HEAD^ --hard\n$ git push --force-with-lease [remote] [branch]\n```\n\nSi no has subido tus cambios, para resetear Git al estado en el que estaba antes de realizar tu último commit (mientras mantengas tus cambios en staging):\n\n```\n(my-branch)$ git reset --soft HEAD^\n```\n\nEsto solo funciona si no subiste tu commit. Si lo hiciste, la única cosa segura por hacer es `git revert SHAofBadCommit`. Eso creará un nuevo commit que deshace todos los cambios del anterior commit. O,  si la rama que subiste es segura ante reorganizaciones (ej. otros desarrolladores no esperan recibir cambios desde ahí), puedes usar `git push --force-with-lease`. Para más, mira [la sección de arriba](#quiero-borrar-o-remover-mi-ultimo-commit).\n\n### Eliminar/remover commit arbitrario\n\nLa misma advertencia de arriba. Nunca hagas esto si es posible.\n\n```sh\n$ git rebase --onto SHA1_OF_BAD_COMMIT^ SHA1_OF_BAD_COMMIT\n$ git push --force-with-lease [remote] [branch]\n```\n\nO haz un [rebase-interactivo](#rebase-interactivo) y remueve la(s) línea(s) correspondientes al commit que quieres remover.\n\n### Intenté subir mi commit enmendado al repositorio remoto, pero obtuve un mensaje de error\n\n```sh\nTo https://github.com/yourusername/repo.git\n! [rejected]        mybranch -> mybranch (non-fast-forward)\nerror: failed to push some refs to 'https://github.com/tanay1337/webmaker.org.git'\nhint: Updates were rejected because the tip of your current branch is behind\nhint: its remote counterpart. Integrate the remote changes (e.g.\nhint: 'git pull ...') before pushing again.\nhint: See the 'Note about fast-forwards' in 'git push --help' for details.\n```\n\nTen en cuenta que, al igual que con el rebase (ver más abajo), usar amend **reemplaza el anterior commit con uno nuevo**, por lo que debes forzar el push (`--force-with-lease`) de tus cambios si ya has hecho una confirmación previamente enmendada al repositorio remoto. ¡Ten cuidado cuando hagas esto &ndash; *siempre* asegúrate de especificar una rama!\n\n```sh\n(my-branch)$ git push origin mybranch --force-with-lease\n```\n\nEn general, **evita forzar el push**. Es mejor crear y subir un nuevo commit que forzar el commit enmendado porque causará conflictos en el historial fuente para cualquier otro desarrolador que ha interactuado con la rama en cuestión o una de sus ramas hijas. `--force-with-lease` aún fallará, si alguien más estuviera trabajando en la misma rama que tú, y tu push forzado sobrescribiría sus cambios.\n\nSi estás *absolutamente* seguro que nadie está trabajando en la misma rama o que tú quieres actualizar la rama *incondicionalmente*, puedes usar `--force` (`-f`), pero esto debería ser evitado en general.\n\n### Accidentalmente hice un hard reset y quiero mis cambios de vuelta\n\nSi accidentalmente hiciste `git reset --hard`, puedes volver a obtener tus commits de vuelta ya que git mantiene un registro de todo durante unos días.\n\n```sh\n(main)$ git reflog\n```\n\nVerás una lista de tus antiguos commits, y un commit para el reset. Escoge el SHA del commit al que quieres retornar y has el reset de nuevo:\n\n```sh\n(main)$ git reset --hard SHA1234\n```\n\nY deberías estar ubicado en ese commit.\n\n### Accidentalment hice un commit y empujé una fusión\n\nSi accidentalmente fusionaste una rama a la principal de desarrollo antes de que esté lista para fusionar, todavía puedes deshacer esa fusión. Pero hay un problema: Un commit de fusión tiene más de un padre (usualmente 2).\n\nEl comando a usar\n```sh\n(feature-branch)$ git revert -m 1 <commit>\n```\ndonde la opción -m 1 option menciona seleccionar el padre número 1 (la rama en la cual se hizo la fusión) como el padre a revertirlo.\n\nNota: el número padre no es un identificador de commit. Más bien, un commit de fusión tiene una línea `Merge: 8e2ce2d 86ac2e7`. El número padre empieza con el número 1 como índice, el primer identificador es número 1, el segundo es el número 2, y así\n\n### Accidentalmente hice un commit y empujé archivos que contienen data sensible\n\nSi accidentalment empujaste archivos que contienen data sensible (contraseñas, llaves, etc.), puedes modificar el commit previo. Ten en mente que una vez que hayas hecho un commit, debes considerar cualquier información que éste contiene para ser empujado. Estos pasos pueden remover la data sensible de tu repo público o tu copia local, pero **no puedes** remover la data sensible de copias jaladas de otras personas. Si quieres hacer un commit de una contraseña, **cámbialo de inmediato**. Si hiciste commit de una llave, **regenérala de inmediato**. Modificar el commit enviado no es suficiente, ya que cualquiera podría haber retirado el commit original que contiene sus datos confidenciales en ese tiempo.\n\nSi editas un archivo y remueves la data sensible, entonces ejecuta\n```sh\n(feature-branch)$ git add edited_file\n(feature-branch)$ git commit --amend --no-edit\n(feature-branch)$ git push --force-with-lease origin [branch]\n```\n\nSi quieres remover un archivo entero (pero mantenerlo localmente), entonces ejecuta\n```sh\n(feature-branch)$ git rm --cached sensitive_file\necho sensitive_file >> .gitignore\n(feature-branch)$ git add .gitignore\n(feature-branch)$ git commit --amend --no-edit\n(feature-branch)$ git push --force-with-lease origin [branch]\n```\nAlternativamente guarda tu data sensible en variables de entorno locales.\n\nSi quieres remover completamente un archivo completo (y no mantenerlo localmente), entonces ejecuta\n```sh\n(feature-branch)$ git rm sensitive_file\n(feature-branch)$ git commit --amend --no-edit\n(feature-branch)$ git push --force-with-lease origin [branch]\n```\n\nSi haz hecho otros commits durante ese tiempo (ej. la data sensible está en un commit antes de ese commit), necesitarás hacer un rebase.\n\n## Staging\n\n### Necesito agregar otros cambios al commit anterior\n\n```sh\n(mi-rama*)$ git commit --amend\n```\n\n### Quiero agregar parte de un nuevo archivo, pero no todo el archivo\n\nNormalmente, si deseas representar parte de un archivo, ejecuta esto:\n\n```sh\n$ git add --patch archivo.x\n```\n\n`-p` funcionará para abreviar. Esto abrirá el modo interactivo. Puedes usar la opción `s` para dividir la confirmación; sin embargo, si el archivo es nuevo, no tendrás esta opción. Para agregar un nuevo archivo, usa esto:\n\n```sh\n$ git add -N archivo.x\n```\n\nLuego, necesitarás usar la opción `e` para elegir manualmente qué líneas agregar. Ejecutando `git diff --cached` o\n`git diff -staged` se mostrará qué líneas ha comparado con las que todavía se guardan localmente.\n\n### Quiero agregar cambios en un archivo a dos commits diferentes\n\n`git add` agregará el archivo completo a un commit. `git add -p` te permitirá seleccionar interactivamente los cambios que deseas agregar.\n\n### Quiero crear mis ediciones sin escalonar y eliminar mis ediciones escalonadas\n\nEsto es complicado. Lo mejor que creo es que debes esconder tus ediciones sin escena. Luego, restablecer. Después de eso, muestra tus cambios ocultos y agrégalos.\n\n```sh\n$ git stash -k\n$ git reset --hard\n$ git stash pop\n$ git add -A\n```\n\n## Ediciones sin escena\n\n### Deseo mover mis ediciones sin escena a una nueva rama\n\n```sh\n$ git checkout -b mi-rama\n```\n\n### Deseo mover mis ediciones sin escena a una rama diferente existente\n\n```sh\n$ git stash\n$ git checkout my-rama\n$ git stash pop\n```\n\n### Quiero descartar mis cambios locales no confirmados (en escena y sin escena)\n\nSi deseas descartar todos los cambios organizados y no supervisados ​​locales, puede hacer esto:\n\n```sh\n(mi-rama) $ git reset --hard\n# o\n(main) $ git checkout -f\n```\n\nEsto borrará todos los archivos que hayas organizado con `git add`:\n\n```sh\n$ git reset\n```\n\nEsto revertirá todos los cambios locales no confirmados (se debe ejecutar en la raíz del repositorio):\n\n```sh\n$ git checkout .\n```\n\nTambién puedes revertir cambios no confirmados a un archivo o directorio en particular:\n\n```sh\n$ git checkout [some_dir | file.txt]\n```\n\nOtra forma de revertir todos los cambios no confirmados (más largo de escribir, pero funciona desde cualquier subdirectorio):\n\n```sh\n$ git reset --hard HEAD\n```\n\nEsto eliminará todos los archivos locales sin seguimiento, por lo que solo se conservarán los archivos rastreados por Git:\n\n```sh\n$ git clean -fd\n```\n\n`-x` también eliminará todos los archivos ignorados.\n\n### Quiero descartar cambios específicos no planificados\n\nCuando desees deshacerse de algunos, pero no de todos los cambios en su copia de trabajo.\n\nVerifica los cambios no deseados, mantén buenos cambios.\n\n```sh\n$ git checkout -p\n# Responde y a todos los cambios que desea eliminar\n```\n\nOtra estrategia implica el uso de `stash`. Guarda todos los buenos cambios, restablece la copia de trabajo y vuelve a aplicar los buenos cambios.\n\n```sh\n$ git stash -p\n# Selecciona todos los cambios que desea guardar\n$ git reset --hard\n$ git stash pop\n```\n\nAlternativamente, oculta sus cambios no deseados, y luego deja el escondite.\n\n```sh\n$ git stash -p\n# Selecciona todos los cambios que no quiere guardar\n$ git stash drop\n```\n\n### Quiero descartar archivos específicos no escaneados\n\nCuando desees deshacerse de un archivo específico en su copia de trabajo.\n\n```sh\n$ git checkout myFile\n```\n\nAlternativamente, para descartar varios archivos en su copia de trabajo, enumera todos.\n\n```sh\n$ git checkout myFirstFile mySecondFile\n```\n\n### Deseo descartar solo mis cambios locales sin escenario\n\nCuando desees deshacerse de todos sus cambios no confirmados locales sin confirmar\n\n```sh\n$ git checkout .\n```\n### Quiero descartar todos mis archivos sin seguimiento\n\nCuando desees deshacerse de todos sus archivos sin seguimiento\n\n```sh\n$ git clean -f\n```\n\n## Ramas\n\n### Quiero enumerar todas las ramas\n\nEnumerar ramas locales\n\n```sh\n$ git branch\n```\n\nEnumerar ramas remotas\n\n```sh\n$ git branch -r\n```\n\nListar todas las ramas (tanto locales como remotas)\n\n```sh\n$ git branch -a\n```\n\n### Crear una rama desde una confirmación\n\n```sh\n$ git checkout -b <branch> <SHA1_OF_COMMIT>\n```\n### Hice pull de / en la rama incorrecta\n\nEsta es otra oportunidad de usar `git reflog` para ver dónde apuntó el HEAD antes del mal tirón.\n\n```sh\n(main) $ git reflog\nab7555f HEAD @ {0}: pull-wrong-branch: Fast-forward\nc5bc55a HEAD @ {1}: checkout: checkout message goes here\n```\n\nSimplemente restablece tu rama al commit deseado:\n\n```sh\n$ git reset --hard c5bc55a\n```\n\nHecho.\n\n### Quiero descartar confirmaciones locales para que mi rama sea la misma que la del servidor\n\nConfirma que no ha enviado sus cambios al servidor.\n\n`git status` debe mostrar cuántos commits tienes adelantado al origin:\n\n```sh\n(my-branch)$ git status\n# On branch my-branch\n# Your branch is ahead of 'origin/my-branch' by 2 commits.\n#   (use \"git push\" to publish your local commits)\n#\n```\n\nUna forma de reiniciar para hacer coincidir el origin (tener lo mismo que lo que está en el control remoto) es hacer esto:\n\n```sh\n(my-branch) $ git reset --hard origin/my-branch\n```\n\n### Hice commit a main en lugar de una nueva rama\n\nCrea la nueva rama mientras permaneces en main:\n\n```sh\n(main) $ git branch my-branch\n```\n\nRestablece la rama main al commit anterior:\n\n```sh\n(main) $ git reset --hard HEAD ^\n```\n\n`HEAD ^` es la abreviatura de `HEAD ^ 1`. Esto representa el primer padre de `HEAD`, del mismo modo` HEAD ^ 2` representa el segundo padre del commit (las fusiones pueden tener 2 padres).\n\nTen en cuenta que `HEAD ^ 2` ** no ** es lo mismo que` HEAD ~ 2` (vea [este enlace] (http://www.paulboxley.com/blog/2011/06/git-caret-and-tilde) para más información).\n\nAlternativamente, si no quieres usar `HEAD ^`, averigüe a qué hash de confirmación quieres establecer su rama principal (`git log` debería ser el truco). Luego reinicia a ese hash. `git push` se asegurará de que este cambio se refleje en su control remoto.\n\nPor ejemplo, si el hash del commit en el que se supone que está su rama principal es `a13b85e`:\n\n```sh\n(main) $ git reset --hard a13b85e\nHEAD is now at a13b85e\n```\n\nVerifique la nueva rama para continuar trabajando:\n\n```sh\n(main) $ git checkout my-branch\n```\n\n### Quiero mantener todo el archivo de otro ref-ish\n\nSupongamos que tienes un pico activo (ver nota), con cientos de cambios. Todo está funcionando. Ahora, te comprometes con otra rama para guardar ese trabajo:\n\n```sh\n(solución) $ git add -A && git commit -m \"Agregando todos los cambios desde este pico en un gran compromiso.\"\n```\n\nCuando desees colocarlo en una rama (tal vez función, tal vez `develop`), te interesa conservar archivos completos. Quieres dividir tu gran compromiso en otros más pequeños.\n\nDigamos que tienes:\n\n  * branch `solution`, con la solución para tu spike. Uno por delante de `develop`.\n  * branch `develop`, donde desea agregar sus cambios.\n\nPuedes resolverlo llevando los contenidos a tu rama:\n\n```sh\n(develop) $ git checkout solution - file1.txt\n```\n\nEsto obtendrá los contenidos de ese archivo en la 'solución' de la rama a su rama `develop`:\n\n```sh\n# On branch develop\n# Your branch is up-to-date with 'origin/develop'.\n# Changes to be committed:\n#  (use \"git reset HEAD <file>...\" to unstage)\n#\n#        modified:   file1.txt\n```\n\nEntonces, haz un commit como de costumbre.\n\nNota: Las soluciones de Spike están hechas para analizar o resolver el problema. Estas soluciones se utilizan para la estimación y se descartan una vez que todos obtienen una visualización clara del problema. ~ [Wikipedia] (https://en.wikipedia.org/wiki/Extreme_programming_practices).\n\n### Realicé varios commits en una sola rama que debería estar en diferentes ramas\n\nDigamos que estás en tu rama principal. Al ejecutar `git log`, verás que ha realizado dos commits:\n\n```sh\n(main) $ git log\n\ncommit e3851e817c451cc36f2e6f3049db528415e3c114\nAuthor: Alex Lee <alexlee@example.com>\nDate:   Tue Jul 22 15:39:27 2014 -0400\n\n    Bug #21 - Added CSRF protection\n\ncommit 5ea51731d150f7ddc4a365437931cd8be3bf3131\nAuthor: Alex Lee <alexlee@example.com>\nDate:   Tue Jul 22 15:39:12 2014 -0400\n\n    Bug #14 - Fixed spacing on title\n\ncommit a13b85e984171c6e2a1729bb061994525f626d14\nAuthor: Aki Rose <akirose@example.com>\nDate:   Tue Jul 21 01:12:48 2014 -0400\n\n    First commit\n```\n\nToma nota de nuestros hashes de confirmación para cada error (`e3851e8` para # 21,` 5ea5173` para # 14).\n\nPrimero, restablece la rama principal al commit correcto (`a13b85e`):\n\n```sh\n(main)$ git reset --hard a13b85e\nHEAD is now at a13b85e\n```\n\nAhora, puedes crear una nueva rama para la rama bug # 21:\n\n```sh\n(main) $ git checkout -b 21\n(21) $\n```\n\nAhora, * selecciona con precisión * el commit para el error # 21 en la parte superior de la rama. Eso significa que aplicarás ese commit, y solo ese commit, directamente sobre el HEAD que estés.\n\n```sh\n(21) $ git cherry-pick e3851e8\n```\n\nEn este punto, existe la posibilidad de que haya conflictos. Consulta la sección ** Hubo conflictos ** (# conflicto de fusión) en la [sección interactiva de rebase más arriba] (# interactive-rebase) para saber cómo resolver conflictos.\n\nAhora creamos una nueva rama para el error # 14, también basado en el main\n\n```sh\n(21) $ git checkout main\n(main) $ git checkout -b 14\n(14) $\n```\n\nY finalmente, vamos a seleccionar el compromiso para el error # 14:\n\n```sh\n(14) $ git cherry-pick 5ea5173\n```\n\n### Quiero eliminar las ramas locales que se eliminaron en sentido ascendente\nUna vez que fusiona una solicitud de extracción en GitHub, le da la opción de eliminar la rama fusionada en su fork. Si no tiene planeado seguir trabajando en la rama, es más limpio eliminar las copias locales de la rama para que no termine complicando su proceso de pago con muchas ramas obsoletas.\n\n```sh\n$ git fetch -p upstream\n```\n\ndonde, 'ascendente' es el control remoto desde el que desea recuperar.\n\n### Accidentalmente borré mi rama\n\nSi empujas regularmente hacia el control remoto, deberías estar seguro la mayor parte del tiempo. Pero aún así a veces puede terminar borrando sus ramaes. Digamos que creamos una rama y creamos un nuevo archivo:\n\n```sh\n(main)$ git checkout -b my-branch\n(my-branch)$ git branch\n(my-branch)$ touch foo.txt\n(my-branch)$ ls\nREADME.md foo.txt\n```\n\nVamos a agregarlo y hacer el commit.\n\n```sh\n(my-branch)$ git add .\n(my-branch)$ git commit -m 'foo.txt added'\n(my-branch)$ foo.txt added\n 1 files changed, 1 insertions(+)\n create mode 100644 foo.txt\n(my-branch)$ git log\n\ncommit 4e3cd85a670ced7cc17a2b5d8d3d809ac88d5012\nAuthor: siemiatj <siemiatj@example.com>\nDate:   Wed Jul 30 00:34:10 2014 +0200\n\n    foo.txt added\n\ncommit 69204cdf0acbab201619d95ad8295928e7f411d5\nAuthor: Kate Hudson <katehudson@example.com>\nDate:   Tue Jul 29 13:14:46 2014 -0400\n\n    Fixes #6: Force pushing after amending commits\n```\n\nAhora estamos volviendo a \"main\" y \"accidentalmente\" eliminando nuestra rama.\n\n```sh\n(my-branch)$ git checkout main\nSwitched to branch 'main'\nYour branch is up-to-date with 'origin/main'.\n(main)$ git branch -D my-branch\nDeleted branch my-branch (was 4e3cd85).\n(main)$ echo oh noes, deleted my branch!\noh noes, deleted my branch!\n```\n\nEn este punto, debe familiarizarse con 'reflog', un registrador actualizado. Almacena el historial de todas las acciones en el repositorio.\n\n```\n(main)$ git reflog\n69204cd HEAD@{0}: checkout: moving from my-branch to main\n4e3cd85 HEAD@{1}: commit: foo.txt added\n69204cd HEAD@{2}: checkout: moving from main to my-branch\n```\n\nComo puede ver, hemos confirmado el hash de nuestra rama eliminada. Veamos si podemos restaurar nuestra rama eliminada.\n\n```sh\n(main)$ git checkout -b my-branch-help\nSwitched to a new branch 'my-branch-help'\n(my-branch-help)$ git reset --hard 4e3cd85\nHEAD is now at 4e3cd85 foo.txt added\n(my-branch-help)$ ls\nREADME.md foo.txt\n```\n\nVoila! Recuperamos nuestro archivo eliminado. `git reflog` también es útil cuando el rebase es terriblemente incorrecto.\n\n### Quiero eliminar una rama\n\nPara eliminar una rama remota:\n\n```sh\n(main) $ git push origin --delete my-branch\n```\n\nTambién puedes hacer:\n\n```sh\n(main) $ git push origin: my-branch\n```\n\nPara eliminar una rama local:\n\n```sh\n(main) $ git branch -d my-branch\n```\n\nPara eliminar una rama local que * no * se ha fusionado con la rama actual o una cadena ascendente:\n\n```sh\n(main) $ git branch -D my-branch\n```\n\n### Quiero eliminar varias ramas\n\nSupongamos que quiere eliminar todas las ramas que comienzan con `fix /`:\n\n```sh\n(main) $ git rama | grep 'fix /' | xargs git branch -d\n```\n\n### Quiero cambiar el nombre de una rama\n\nPara cambiar el nombre de la rama actual (local):\n\n```sh\n(main) $ git branch -m new-name\n```\n\nPara cambiar el nombre de una rama diferente (local):\n\n```sh\n(main) $ git branch -m old-name new-name\n```\n\n### Quiero hacer checkout en una rama remota en la que alguien más está trabajando\n\nPrimero, busca todas las ramas desde el control remoto:\n\n```sh\n(main)$ git fetch --all\n```\n\nDigamos que quieres hacer checkout a `daves` desde el repositorio remoto.\n\n```sh\n(main)$ git checkout --track origin/daves\nBranch daves set up to track remote branch daves from origin.\nSwitched to a new branch 'daves'\n```\n\n(`--track` es la abreviatura de 'git checkout -b [branch] [remotename] / [branch]`)\n\nEsto le dará una copia local de la rama `daves`, y cualquier actualización que se haya enviado también se mostrará de forma remota.\n\n### Quiero crear una nueva rama remota desde la actual local\n\n```sh\n$ git push <remote>\n```\n\nSi también desea establecer esa rama remota como cadena arriba para la actual, use lo siguiente:\n\n```sh\n$ git push -u <remote>\n```\n\nCon el modo `upstream` y el modo `simple` (predeterminado en Git 2.0) de la configuración `push.default`, el siguiente comando empujará la bifurcación actual con respecto a la bifurcación remota que se ha registrado previamente con `-u `:\n\n```sh\n$ git push\n```\n\nEl comportamiento de los otros modos de ```git push``` se describe en el documento de push.default.\n\n### Quiero configurar una rama remota como upstream para una rama local\n\nPuedes establecer una rama remota como ascendente para la sucursal local actual usando:\n\n```sh\n$ git branch --set-upstream-to [remotename]/[branch]\n# or, using the shorthand:\n$ git branch -u [remotename]/[branch]\n```\n\nPara establecer la rama remota ascendente para otra rama local:\n\n```sh\n$ git branch -u [remotename] / [branch] [local-branch]\n```\n\n### Quiero configurar mi HEAD para rastrear la rama remota predeterminada\n\nAl verificar tus ramas remotas, puedes ver en qué rama remota está rastreando el HEAD. En algunos casos, esta no es la rama deseada.\n\n```sh\n$ git branch -r\n  origin/HEAD -> origin/gh-pages\n  origin/main\n```\n\nCambiar `origin / HEAD` para rastrear` origin / main`, puedes ejecutar este comando:\n\n```sh\n$ git remote set-head origin --auto\norigin/HEAD set to main\n```\n\n## Rebasing y Merging\n\n### Quiero deshacer rebase/merge\n\nEs posible que hayas fusionado o rediseñado tu rama actual con una rama incorrecta, o que no puedas resolverlo o finalizar el proceso de rebase/merge. Git guarda el puntero original HEAD en una variable llamada ORIG_HEAD antes de realizar operaciones peligrosas, por lo que es sencillo recuperar la rama en el estado anterior al rebase/merge.\n\n\n```sh\n(my-branch)$ git reset --hard ORIG_HEAD\n```\n\n### Hice rebase, pero no quiero forzar el push\n\nDesafortunadamente, debes forzar el push, si deseas que esos cambios se reflejen en la rama remota. Esto se debe a que ha cambiado el historial. La rama remota no aceptará cambios a menos que fuerce la inserción. Esta es una de las principales razones por las que muchas personas usan un flujo de trabajo de merge, en lugar de un flujo de trabajo de reordenación: los equipos grandes pueden tener problemas con el impulso de los desarrolladores. Usa esto con precaución. Una forma más segura de utilizar rebase no es reflejar los cambios en la rama remota, sino hacer lo siguiente:\n\n\n```sh\n(main)$ git checkout my-branch\n(my-branch)$ git rebase -i main\n(my-branch)$ git checkout main\n(main)$ git merge --ff-only my-branch\n```\n\nPara obtener más información, consulte [este thread SO] (https://stackoverflow.com/questions/11058312/how-can-i-use-git-rebase-without-requiring-a-forced-push).\n\n### Necesito combinar commits\n\nSupongamos que estás trabajando en una rama que es / se convertirá en un pull request contra main. En el caso más simple, cuando todo lo que quiere hacer es combinar todos los commits en uno solo y no le importa cometer timestamps, puedes restablecer y volver a hacer el commit. Asegúrate de que la rama principal esté actualizada y de que se hayan confirmado todos los cambios, luego:\n\n```sh\n(my-branch)$ git reset --soft main\n(my-branch)$ git commit -am \"New awesome feature\"\n```\n\nSi deseas más control y también conservar las marcas de tiempo, debe hacer algo que se llame un rebase interactivo:\n\n\n```sh\n(my-branch)$ git rebase -i main\n```\n\nSi no estás trabajando contra otra rama tendrás que volver a establecer una base relativa a tu `HEAD`. Si quieres aplastar las últimas 2 confirmaciones, por ejemplo, tendrás que volver a calcular contra `HEAD ~ 2`. Para los últimos 3, `HEAD ~ 3`, etc.\n\n```sh\n(main)$ git rebase -i HEAD~2\n```\n\nDespués de ejecutar el comando de rebase interactivo, verás algo como esto en tu editor de texto:\n\n\n```vim\npick a9c8a1d Some refactoring\npick 01b2fd8 New awesome feature\npick b729ad5 fixup\npick e3851e8 another fix\n\n# Rebase 8074d12..b729ad5 onto 8074d12\n#\n# Commands:\n#  p, pick = use commit\n#  r, reword = use commit, but edit the commit message\n#  e, edit = use commit, but stop for amending\n#  s, squash = use commit, but meld into previous commit\n#  f, fixup = like \"squash\", but discard this commit's log message\n#  x, exec = run command (the rest of the line) using shell\n#\n# These lines can be re-ordered; they are executed from top to bottom.\n#\n# If you remove a line here THAT COMMIT WILL BE LOST.\n#\n# However, if you remove everything, the rebase will be aborted.\n#\n# Note that empty commits are commented out\n```\n\nTodas las líneas que comienzan con `#` son comentarios, no afectarán a tu rebase.\n\nReemplaza los comandos `pick` con cualquiera en la lista anterior, y también puedes eliminar commits eliminando las líneas correspondientes.\n\nPor ejemplo, si deseas **dejar el commit más antiguo (el primero) solo y combinar todos los siguientes commits con el segundo más antiguo**, debes editar la letra junto a cada commit, excepto la primera y la segunda para decir `f` :\n\n```vim\npick a9c8a1d Some refactoring\npick 01b2fd8 New awesome feature\nf b729ad5 fixup\nf e3851e8 another fix\n```\n\nSi deseas combinar estos commits **y cambiar el nombre del commit**, también debes agregar una `r` junto al segundo commit o simplemente usar` s` en lugar de `f`:\n\n```vim\npick a9c8a1d Some refactoring\npick 01b2fd8 New awesome feature\ns b729ad5 fixup\ns e3851e8 another fix\n```\n\nA continuación, puedes cambiar el nombre del commit en el siguiente mensaje de texto que aparece.\n\n\n```vim\nNewer, awesomer features\n\n# Please enter the commit message for your changes. Lines starting\n# with '#' will be ignored, and an empty message aborts the commit.\n# rebase in progress; onto 8074d12\n# You are currently editing a commit while rebasing branch 'main' on '8074d12'.\n#\n# Changes to be committed:\n#   modified:   README.md\n#\n\n```\n\nSi todo tiene éxito, deberías ver algo como esto:\n\n```sh\n(main)$ Successfully rebased and updated refs/heads/main.\n```\n\n#### Estrategia de merge segura\n`--no-commit` realiza el merge, pero simula que la combinación falló y no se confirma automáticamente, lo que le da al usuario la oportunidad de inspeccionar y modificar aún más el resultado de la combinación antes de realizar la tarea. `no-ff` mantiene la evidencia de que alguna vez existió una rama de características, manteniendo la historia del proyecto consistente.\n\n```sh\n(main)$ git merge --no-ff --no-commit my-branch\n```\n\n#### Necesito fusionar una rama en un solo commit\n\n```sh\n(main)$ git merge --squash my-branch\n```\n\n#### Quiero combinar solo los commits sin haber hecho push\n\nA veces tiene varios commits en progreso que deseas combinar antes de hacer push. No deseas combinar accidentalmente ningún commit que ya haya sido pusheado porque otra persona ya haya realizado commits que les hagan referencia.\n\n```sh\n(main)$ git rebase -i @{u}\n```\n\nEsto hará una base de datos interactiva que enumera solo los commits que aún no has enviado, por lo que será seguro reordenar / arreglar / aplastar cualquier elemento de la lista.\n\n#### Necesito abortar el merge\n\nA veces, la fusión puede producir problemas en ciertos archivos, en esos casos podemos usar la opción `abort` para abortar el proceso actual de resolución de conflictos, y tratar de reconstruir el estado previo a la fusión.\n\n```sh\n(my-branch)$ git merge --abort\n```\n\nEste comando está disponible desde la versión de Git> = 1.7.4\n\n### Comprobar si se combinan todos los commits de un branch\n\nPara comprobar si todos los commits de una rama se fusionan en otra, debe distinguir las cabeceras (o los commits) de esas ramas:\n\n```sh\n(main)$ git log --graph --left-right --cherry-pick --oneline HEAD...feature/120-on-scroll\n```\n\nEsto te dirá si hay commits en una pero no en la otra, y te dará una lista de las no compartidas entre las ramas. Otra opción es hacer esto:\n\n```sh\n(main)$ git log main ^feature/120-on-scroll --no-merges\n```\n\n### Posibles problemas con rebase interactivos\n\n#### La pantalla de edición de rebase dice 'noop'\n\nSi estás viendo esto:\n```\nnoop\n```\n\nEso significa que estás tratando de volver a establecer una base contra una rama que está en un commit idéntico, o está *delante* de tu rama actual. Puedes probar:\n\n* asegurándote de que tu rama principal esté donde debería estar\n* rebase contra `HEAD ~ 2` o anterior a su lugar\n\n#### Hubo conflictos\n\nSi no puedes completar correctamente el rebase, es posible que tengas que resolver conflictos.\n\nPrimero ejecuta `git status` para ver qué archivos tienen conflictos en ellos:\n\n```sh\n(my-branch)$ git status\nOn branch my-branch\nChanges not staged for commit:\n  (use \"git add <file>...\" to update what will be committed)\n  (use \"git checkout -- <file>...\" to discard changes in working directory)\n\n  both modified:   README.md\n```\n\nEn este ejemplo, `README.md` tiene conflictos. Abre ese archivo y busca lo siguiente:\n\n```vim\n   <<<<<<< HEAD\n   some code\n   =========\n   some code\n   >>>>>>> new-commit\n```\n\nTendrás que resolver las diferencias entre el código que se agregó en tu nuevo commit (en el ejemplo, todo desde la línea media hasta `new-commit ') y tu' HEAD '.\n\nSi deseas conservar la versión del código de una rama, puedes usar `--us` o` --theirs`:\n\n```sh\n(main*)$ git checkout --ours README.md\n```\n\n- Cuando haces *merge*, usa `--ours` para mantener los cambios de la rama local, o` --theirs` para mantener los cambios de la otra rama.\n- Cuando haces *rebase*, usa `--theirs` para mantener los cambios de la rama local, o` --ours` para mantener los cambios de la otra rama. Para obtener una explicación de este intercambio, consulte [esta nota en la documentación de Git] (https://git-scm.com/docs/git-rebase#Documentation/git-rebase.txt---merge).\n\nSi las fusiones son más complicadas, puede usar un editor visual diff:\n\n```sh\n(main*)$ git mergetool -t opendiff\n```\n\nDespués de haber resuelto todos los conflictos y probado el código, `git add` los archivos que has cambiado, y luego continúa el rebase con` git rebase --continue`\n\n```sh\n(my-branch)$ git add README.md\n(my-branch)$ git rebase --continue\n```\n\nSi después de resolver todos los conflictos terminas con un árbol idéntico a lo que era antes del commit, necesitas `git rebase --skip` en su lugar.\n\nSi en algún momento deseas detener todo el rebase y volver al estado original de tu rama, puedes hacer:\n\n```sh\n(my-branch)$ git rebase --abort\n```\n\n## Stash\n\n### Usar stash en todos los cambios\n\nPara esconder todas las ediciones de tu directorio de trabajo\n\n```sh\n$ git stash\n```\n\nSi también quiere esconder archivos sin seguimiento, use la opción `-u`.\n\n```sh\n$ git stash -u\n```\n\n### Usar stash para archivos específicos\n\nPara esconder solo un archivo de tu directorio de trabajo\n\n```sh\n$ git stash push working-directory-path/filename.ext\n```\n\nPara esconder varios archivos de tu directorio de trabajo\n\n```sh\n$ git stash push working-directory-path/filename1.ext working-directory-path/filename2.ext\n```\n\n### Usar stash con un mensaje\n\n```sh\n$ git stash save <message>\n```\n\n### Aplicar un stash específico de la lista\n\nPrimero revisa la lista de stash con mensaje usando\n\n```sh\n$ git stash list\n```\n\nLuego selecciona un stash específico de la lista usando\n\n```sh\n$ git stash apply \"stash@{n}\"\n```\n\nAquí, 'n' indica la posición del stash en la pila. El stash más alto será la posición 0.\n\n## Búsqueda\n\n### Quiero encontra un string en algún commit\n\nPara encontrar un determinada string que se introdujo en cualquier commit, puedes usar la siguiente estructura:\n\n```sh\n$ git log -S \"string to find\"\n```\n\nParámetros comunes:\n\n* `--source` significa mostrar el nombre de la referencia dada en la línea de comando por la cual se llegó a cada commit.\n\n* `--all` significa comenzar desde cada rama.\n\n* `--reverse` imprime en orden inverso, significa que mostrará el primer commit que realizó el cambio.\n\n### Quiero buscar por autor / committer\n\nPara encontrar todos los commits por autor / committer, puedes usar:\n\n```sh\n$ git log --author=<name or email>\n$ git log --committer=<name or email>\n```\n\nTen en cuenta que autor y committer no son lo mismo. El `--autor` es la persona que originalmente escribió el código; por otro lado, el `--committer` es la persona que subió el código en nombre del autor original.\n\n### Quiero enumerar commits que contienen archivos específicos\n\nPara encontrar todos los commits que contienen un archivo específico, puedes usar:\n\n```sh\n$ git log -- <path to file>\n```\n\nPor lo general, debes especificar una ruta exacta, pero también puede usar comodines en la ruta y el nombre del archivo:\n\n```sh\n$ git log -- **/*.js\n```\n\nAl usar comodines, es útil informar `--name-status` para ver la lista de archivos comprometidos:\n\n```sh\n$ git log --name-status -- **/*.js\n```\n\n### Encontrar una etiqueta donde se hace referencia a un commit\n\nPara encontrar todas las etiquetas que contienen un commit específico:\n\n```sh\n$ git tag --contains <commitid>\n```\n\n## Submódulos\n\n### Clonar todos los submódulos\n\n```sh\n$ git clone --recursive git://github.com/foo/bar.git\n```\n\nSi ya fue clonado\n\n```sh\n$ git submodule update --init --recursive\n```\n\n### Remover un submódulo\n\nCrear un submódulo es bastante simple, pero eliminarlos no. Los comandos que necesitas son:\n\n```sh\n$ git submodule deinit submodulename\n$ git rm submodulename\n$ git rm --cached submodulename\n$ rm -rf .git/modules/submodulename\n```\n\n## Objetos diversos\n\n### Restaurar un archivo eliminado\n\nPrimero encuentra el commit donde el archivo existió por última vez:\n\n```sh\n$ git rev-list -n 1 HEAD -- filename\n```\n\nLuego hazle checkout a ese archivo\n\n```\ngit checkout deletingcommitid^ -- filename\n```\n\n### Eliminar una etiqueta\n\n```sh\n$ git tag -d <tag_name>\n$ git push <remote> :refs/tags/<tag_name>\n```\n\n### Recuperar una etiqueta eliminada\n\nSi deseas recuperar una etiqueta que ya fue eliminada, puede hacerlo siguiendo estos pasos: Primero, debe encontrar la etiqueta inalcanzable:\n\n```sh\n$ git fsck --unreachable | grep tag\n```\n\nToma nota del hash de la etiqueta. Luego, restaura la etiqueta eliminada con la siguiente, haciendo uso de [`git update-ref`] (https://git-scm.com/docs/git-update-ref):\n\n```sh\n$ git update-ref refs/tags/<tag_name> <hash>\n```\n\nTu etiqueta ahora debería haber sido restaurada.\n\n### Patch eliminado\n\nSi alguien envió un pull request en GitHub, pero luego eliminó el fork original, no podrá clonar su repositorio ni usar `git am` como [.diff, .patch] (https://github.com / blog / 967-github-secrets) las URL no están disponibles. Pero puedes verificar el PR utilizando las [referencias especiales de GitHub] (https://gist.github.com/piscisaureus/3342247). Para recuperar el contenido de PR # 1 en una nueva rama llamada pr_1:\n\n```sh\n$ git fetch origin refs/pull/1/head:pr_1\nFrom github.com:foo/bar\n * [new ref]         refs/pull/1/head -> pr_1\n```\n\n### Exportar un repositorio como un archivo Zip\n\n```sh\n$ git archive --format zip --output /full/path/to/zipfile.zip main\n```\n\n## Seguimiento de archivos\n\n### Quiero cambiar el uso de mayúsculas de un nombre de archivo, sin cambiar el contenido del archivo\n\n```sh\n(main)$ git mv --force myfile MyFile\n```\n\n### Quiero sobrescribir los archivos locales cuando hago un git pull\n\n```sh\n(main)$ git fetch --all\n(main)$ git reset --hard origin/main\n```\n\n### Quiero eliminar un archivo de Git pero mantener el archivo\n\n```sh\n(main)$ git rm --cached log.txt\n```\n\n### Quiero revertir un archivo a una revisión específica\n\nSuponiendo que el hash del commit que deseas es c5f567:\n\n```sh\n(main)$ git checkout c5f567 -- file1/to/restore file2/to/restore\n```\n\nSi desea volver a los cambios realizados solo 1 commit antes de c5f567, pase el hash de confirmación como c5f567 ~ 1:\n\n```sh\n(main)$ git checkout c5f567~1 -- file1/to/restore file2/to/restore\n```\n\n## Configuración\n\n### Quiero agregar alias para algunos comandos de Git\n\nEn OS X y Linux, tu archivo de configuración de git se almacena en ```~ / .gitconfig```. He agregado algunos alias de ejemplo que uso como accesos directos (y algunos de mis errores comunes) en la sección `` `[alias]` `` como se muestra a continuación:\n\n```vim\n[alias]\n    a = add\n    amend = commit --amend\n    c = commit\n    ca = commit --amend\n    ci = commit -a\n    co = checkout\n    d = diff\n    dc = diff --changed\n    ds = diff --staged\n    f = fetch\n    loll = log --graph --decorate --pretty=oneline --abbrev-commit\n    m = merge\n    one = log --pretty=oneline\n    outstanding = rebase -i @{u}\n    s = status\n    unpushed = log @{u}\n    wc = whatchanged\n    wip = rebase -i @{u}\n    zap = fetch -p\n```\n\n### Quiero agregar un directorio vacío a mi repositorio\n\n¡No puedes! Git no es compatible con esto, pero hay un truco. Puede crear un archivo .gitignore en el directorio con los siguientes contenidos:\n\n```\n # Ignore everything in this directory\n *\n # Except this file\n !.gitignore\n```\n\nOtra convención común es crear un archivo vacío en la carpeta, titulado .gitkeep.\n\n```sh\n$ mkdir mydir\n$ touch mydir/.gitkeep\n```\n\nTambién puedes nombrar el archivo como .keep, en cuyo caso la segunda línea de arriba sería ```touch mydir / .keep```\n\n### Quiero guardar en caché un nombre de usuario y contraseña para un repositorio\n\nEs posible que tengas un repositorio que requiera autenticación. En ese caso, puedes guardar en caché un nombre de usuario y contraseña para que no tenga que ingresarlos en cada push / pull. Credential helper puede hacer esto por ti.\n\n```sh\n$ git config --global credential.helper cache\n# Set git to use the credential memory cache\n```\n\n```sh\n$ git config --global credential.helper 'cache --timeout=3600'\n# Set the cache to timeout after 1 hour (setting is in seconds)\n```\n\n### Quiero hacer que Git ignore los permisos y cambios en el modo de archivo\n\n```sh\n$ git config core.fileMode false\n```\n\nSi deseas que este sea el comportamiento predeterminado para los usuarios que han iniciado sesión, utilice:\n\n```sh\n$ git config --global core.fileMode false\n```\n\n## No tengo idea de lo que hice mal\n\nEntonces, estás jodido, \"reiniciaste\" algo, o fusionaste la rama incorrecta, o forzaste empujar y ahora no puedes encontrar tus commits. Sabes, en algún momento, estabas bien y quieres volver a un estado en el que estabas.\n\nPara esto está hecho `git reflog`. `reflog` realiza un seguimiento de los cambios en la punta de una rama, incluso si esa sugerencia no está referenciada por una rama o una etiqueta. Básicamente, cada vez que HEAD cambia, se agrega una nueva entrada al reflog. Esto solo funciona para los repositorios locales, lamentablemente, y solo rastrea los movimientos (no los cambios a un archivo que no fueron grabados en ninguna parte, por ejemplo).\n\n```sh\n(main)$ git reflog\n0a2e358 HEAD@{0}: reset: moving to HEAD~2\n0254ea7 HEAD@{1}: checkout: moving from 2.2 to main\nc10f740 HEAD@{2}: checkout: moving from main to 2.2\n```\n\nEl reflog anterior muestra una salida desde main a la rama 2.2 y viceversa. A partir de ahí, hay un restablecimiento completo de un commit más antiguo. La última actividad se representa en la parte superior con la etiqueta 'HEAD @ {0} `.\n\nSi resulta que retrocedió accidentalmente, el reflog contendrá el main de un commit apuntado a (0254ea7) antes de que accidentalmente soltara 2 commits.\n\n```sh\n$ git reset --hard 0254ea7\n```\n\nUsando `git reset` es posible cambiar el main al commit que era antes. Esto proporciona una red de seguridad en caso de que la historia se haya cambiado accidentalmente.\n\n(copiado y editado desde [Fuente] (https://www.atlassian.com/git/tutorials/rewriting-history/git-reflog)).\n\n# Otros recursos\n\n## Libros\n\n* [Pro Git](https://git-scm.com/book/en/v2) - Excelente libro de Scott Chacon y Ben Straub sobre Git\n* [Git Internals](https://github.com/pluralsight/git-internals-pdf) - Otro excelente libro de Scott Chacon sobre Git\n\n## Tutoriales\n\n* [Tutorial de Git de Atlassian](https://www.atlassian.com/git/tutorials) Obtenga Git a la derecha con tutoriales de principiante a avanzado.\n* [Aprende la ramificación de Git](https://learngitbranching.js.org/) Tutorial interactivo de ramificación / fusión / rebase basado en la web\n* [Obteniendo solidez en Git rebase vs. merge](https://medium.com/@porteneuve/getting-solid-at-git-rebase-vs-merge-4fa1a48c53aa)\n* [git-workflow](https://github.com/asmeurer/git-workflow) - [Aaron Meurer](https://github.com/asmeurer) 'Howto sobre el uso de Git para contribuir a repositorios de código abierto\n* [GitHub como flujo de trabajo](https://hugogiraudel.com/2015/08/13/github-as-a-workflow/) - Una interesante idea sobre el uso de GitHub como flujo de trabajo, particularmente con los PR vacíos\n* [Githug](https://github.com/Gazler/githug) - Un juego para aprender más flujos de trabajo de Git\n\n## Scripts y herramientas\n\n* [firstaidgit.io](http://firstaidgit.io/) Una selección de búsqueda de las preguntas más frecuentes de Git\n* [git-extra-commands](https://github.com/unixorn/git-extra-commands) - una colección de scripts extra útiles de Git\n* [git-extras](https://github.com/tj/git-extras) - Utilidades de GIT - resumen de repo, repl, población de registro de cambios, porcentajes de confirmación de autor y más\n* [git-fire](https://github.com/qw3rtman/git-fire) - git-fire es un plugin de Git que ayuda en caso de una emergencia al agregar todos los archivos actuales, comprometerse y empujar a un nuevo rama (para evitar conflictos de combinación).\n* [git-tips](https://github.com/git-tips/tips) - Consejos pequeños de Git\n* [git-town](https://github.com/Originate/git-town) - Soporte genérico de alto nivel de flujo de trabajo de Git! http://www.git-town.com\n\n## Clientes GUI\n* [GitKraken](https://www.gitkraken.com/) - El cliente francamente lujoso de Git, para Windows, Mac y Linux\n* [git-cola](https://git-cola.github.io/) - otro cliente de Git para Windows y OS X\n* [GitUp](https://github.com/git-up/GitUp) - Una interfaz gráfica de usuario nueva que tiene algunas formas muy dogmáticas de lidiar con las complicaciones de Git\n* [gitx-dev](https://rowanj.github.io/gitx/) - otro cliente gráfico de Git para OS X\n* [Sourcetree](https://www.sourcetreeapp.com/) - Simplicity se une a la potencia en una hermosa y gratuita GUI de Git. Para Windows y Mac.\n* [Tower](https://www.git-tower.com/) - cliente gráfico de Git para OS X (pago)\n* [tig](https://jonas.github.io/tig/) - interfaz de texto en modo terminal para Git\n* [Magit](https://magit.vc/) - Interfaz para Git implementada como un paquete de Emacs.\n* [GitExtensions](https://github.com/gitextensions/gitextensions): una extensión de shell, un plugin de Visual Studio 2010-2015 y una herramienta de repositorio de Git independiente.\n* [Fork](https://git-fork.com/) - un cliente de Git rápido y amigable para Mac (beta)\n* [gmaster](https://gmaster.io/) - un cliente de Git para Windows que tiene combinación de 3 vías, analizan refactores, diferencias semánticas y fusión (beta)\n* [gitk](https://git-scm.com/docs/gitk) - un cliente de Git para Linux para permitir una vista simple del estado de repos.\n"
  },
  {
    "path": "README_fr.md",
    "content": "# Règles de vol pour Git\n\n🌍\n*[English](README.md) ∙ [Español](README_es.md)  ∙  [Русский](README_ru.md) ∙ [繁體中文](README_zh-TW.md) ∙ [简体中文](README_zh-CN.md) ∙ [한국어](README_kr.md)  ∙  [Tiếng Việt](README_vi.md) ∙ [Français](README_fr.md) ∙ [日本語](README_ja.md)*\n\n#### C'est quoi des \"règles de vol\" ?\n\nUn guide pour les astronautes (pour les développeur·euse·s utilisant Git, dans le cas présent) sur quoi faire quand les choses se passent mal.\n\n>  *Les règles de vol* représentent l'ensemble des connaissances durement acquises consignées dans des manuels répertoriant, étape par étape, la procédure à suivre si telle chose se produit et pourquoi. Il s'agit essentiellement de procédures d'exploitation standard extrêmement détaillées et spécifiques à chaque scénario. [...]\n\n> La NASA a recueilli nos faux pas, nos désastres et nos solutions depuis le début des années 60, lorsque les équipes terrestres de l'ère Mercury ont commencé à rassembler les \"leçons tirées\" dans un recueil qui répertorie désormais des milliers de situations problématiques, des pannes de moteur aux poignées de trappes cassées en passant par les bugs informatiques, et leurs solutions.\n\n&mdash; Chris Hadfield, *Guide d'un astronaute pour la vie sur Terre*.\n\n#### Conventions pour ce document\n\nPour des raisons de clarté tous les exemples dans ce document utilisent une invite de commande bash personnalisée dans le but d'indiquer la branche actuelle et s'il y a des modifications indexées ou non. La branche se trouve entre parenthèses, et un `*` après le nom de la branche indique des modifications indexées.\n\nToutes les commandes devraient fonctionner pour les versions de Git au moins supérieures à la 2.13.0. Visitez le [site de Git](https://www.git-scm.com/) pour mettre à jour votre version de git locale.\n\n[![Join the chat at https://gitter.im/k88hudson/git-flight-rules](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/k88hudson/git-flight-rules?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n  - [Dépôts](#d%C3%A9p%C3%B4ts)\n    - [Je veux initialiser un dépôt local](#je-veux-initialiser-un-d%C3%A9p%C3%B4t-local)\n    - [Je veux cloner un dépôt distant](#je-veux-cloner-un-d%C3%A9p%C3%B4t-distant)\n  - [Éditer des Commits](#%C3%89diter-des-commits)\n    - [Qu'est-ce que je viens de commiter ?](#quest-ce-que-je-viens-de-commiter-)\n    - [J'ai commis une erreur dans un message de commit](#jai-commis-une-erreur-dans-un-message-de-commit)\n    - [J'ai commit avec le mauvais nom et email dans les configurations](#jai-commit-avec-le-mauvais-nom-et-email-dans-les-configurations)\n    - [Je veux retirer un fichier du commit précédent](#je-veux-retirer-un-fichier-du-commit-pr%C3%A9c%C3%A9dent)\n    - [Je veux supprimer ou retirer mon dernier commit](#je-veux-supprimer-ou-retirer-mon-dernier-commit)\n    - [Supprimer/retirer un commit arbitraire](#supprimerretirer-un-commit-arbitraire)\n    - [J'ai essayé de pousser un commit modifié vers le dépôt distant, mais j'ai eu un message d'erreur](#jai-essay%C3%A9-de-pousser-un-commit-modifi%C3%A9-vers-le-d%C3%A9p%C3%B4t-distant-mais-jai-eu-un-message-derreur)\n    - [J'ai fait un hard reset par accident, et je veux retrouver mes changements](#jai-fait-un-hard-reset-par-accident-et-je-veux-retrouver-mes-changements)\n    - [J'ai commité et poussé une fusion par accident](#jai-commit%C3%A9-et-pouss%C3%A9-une-fusion-par-accident)\n    - [J'ai commité et poussé des fichiers contenant des données sensibles par accident](#jai-commit%C3%A9-et-pouss%C3%A9-des-fichiers-contenant-des-donn%C3%A9es-sensibles-par-accident)\n  - [Indexation](#indexation)\n    - [J'ai besoin d'ajouter des modifications indexées sur le commit précédent](#jai-besoin-dajouter-des-modifications-index%C3%A9es-sur-le-commit-pr%C3%A9c%C3%A9dent)\n    - [Je veux indexer une partie d'un fichier, mais pas tout le fichier](#je-veux-indexer-une-partie-dun-fichier-mais-pas-tout-le-fichier)\n    - [Je veux ajouter les changements d'un fichier dans deux commits différents](#je-veux-ajouter-les-changements-dun-fichier-dans-deux-commits-diff%C3%A9rents)\n    - [Je veux indexer mes modifications indexées, et désindexer mes modifications indexées](#je-veux-indexer-mes-modifications-index%C3%A9es-et-d%C3%A9sindexer-mes-modifications-index%C3%A9es)\n  - [Modifications non indexées](#modifications-non-index%C3%A9es)\n    - [Je veux déplacer mes modifications non indexées vers une nouvelle branche](#je-veux-d%C3%A9placer-mes-modifications-non-index%C3%A9es-vers-une-nouvelle-branche)\n    - [Je veux déplacer mes modifications non indexées vers une branche différente existante](#je-veux-d%C3%A9placer-mes-modifications-non-index%C3%A9es-vers-une-branche-diff%C3%A9rente-existante)\n    - [Je veux me débarrasser de mes modifications locales non commitées (indexées et non-indexées)](#je-veux-me-d%C3%A9barrasser-de-mes-modifications-locales-non-commit%C3%A9es-index%C3%A9es-et-non-index%C3%A9es)\n    - [Je veux me débarrasser de modifications non-indexées spécifiques](#je-veux-me-d%C3%A9barrasser-de-modifications-non-index%C3%A9es-sp%C3%A9cifiques)\n    - [Je veux me débarrasser de fichiers non-indexés spécifiques](#je-veux-me-d%C3%A9barrasser-de-fichiers-non-index%C3%A9s-sp%C3%A9cifiques)\n    - [Je veux me débarrasser de mes modifications locales non-indexées uniquement](#je-veux-me-d%C3%A9barrasser-de-mes-modifications-locales-non-index%C3%A9es-uniquement)\n    - [Je veux me débarrasser de tous mes fichiers non suivis](#je-veux-me-d%C3%A9barrasser-de-tous-mes-fichiers-non-suivis)\n    - [Je veux désindexer un fichier indexé spécifique](#je-veux-d%C3%A9sindexer-un-fichier-index%C3%A9-sp%C3%A9cifique)\n  - [Branches](#branches)\n    - [Je veux lister toutes les branches](#je-veux-lister-toutes-les-branches)\n    - [Créer une branche à partir d'un commit](#cr%C3%A9er-une-branche-%C3%A0-partir-dun-commit)\n    - [J'ai pull depuis/vers la mauvaise branche](#jai-pull-depuisvers-la-mauvaise-branche)\n    - [Je veux supprimer mes commits locaux afin que ma branche soit pareille à celle sur le serveur](#je-veux-supprimer-mes-commits-locaux-afin-que-ma-branche-soit-pareille-%C3%A0-celle-sur-le-serveur)\n    - [J'ai commité sur main au lieu d'une nouvelle branche](#jai-commit%C3%A9-sur-main-au-lieu-dune-nouvelle-branche)\n    - [Je veux séparer tout un fichier d'un autre ref-ish](#je-veux-s%C3%A9parer-tout-un-fichier-dun-autre-ref-ish)\n    - [J'ai fait plusieurs commits sur une même branche qui auraient dû être sur plusieurs branches](#jai-fait-plusieurs-commits-sur-une-m%C3%AAme-branche-qui-auraient-d%C3%BB-%C3%AAtre-sur-plusieurs-branches)\n    - [Je veux supprimer mes branches locales qui ont été supprimée sur le dépôt distant](#je-veux-supprimer-mes-branches-locales-qui-ont-%C3%A9t%C3%A9-supprim%C3%A9e-sur-le-d%C3%A9p%C3%B4t-distant)\n    - [J'ai supprimé ma branche par accident](#jai-supprim%C3%A9-ma-branche-par-accident)\n    - [Je veux supprimer une branche](#je-veux-supprimer-une-branche)\n    - [Je veux supprimer plusieurs branches](#je-veux-supprimer-plusieurs-branches)\n    - [Je veux renommer une branche](#je-veux-renommer-une-branche)\n    - [Je veux me déplacer sur une branche distante sur laquelle quelqu'un est en train de travailler](#je-veux-me-d%C3%A9placer-sur-une-branche-distante-sur-laquelle-quelquun-est-en-train-de-travailler)\n    - [Je veux créer une nouvelle branche distante à partir de celle en locale](#je-veux-cr%C3%A9er-une-nouvelle-branche-distante-%C3%A0-partir-de-celle-en-locale)\n    - [Je veux configurer une branche distante en tant qu'upstream pour une branche locale](#je-veux-configurer-une-branche-distante-en-tant-quupstream-pour-une-branche-locale)\n    - [Je veux configurer mon HEAD pour suivre la branche distante par défaut](#je-veux-configurer-mon-head-pour-suivre-la-branche-distante-par-d%C3%A9faut)\n    - [J'ai fait des modifications sur la mauvaise branche](#jai-fait-des-modifications-sur-la-mauvaise-branche)\n  - [Rebaser et fusionner](#rebaser-et-fusionner)\n    - [Je veux annuler un rebase/merge](#je-veux-annuler-un-rebasemerge)\n    - [J'ai rebase, mais je ne veux pas pousser de force](#jai-rebase-mais-je-ne-veux-pas-pousser-de-force)\n    - [J'ai besoin de combiner des commits](#jai-besoin-de-combiner-des-commits)\n      - [Stratégie de fusion sûre](#strat%C3%A9gie-de-fusion-s%C3%BBre)\n      - [J'ai besoin de fusionner deux branches en un seul commit](#jai-besoin-de-fusionner-deux-branches-en-un-seul-commit)\n      - [Je veux combiner les commits non poussés uniquement](#je-veux-combiner-les-commits-non-pouss%C3%A9s-uniquement)\n      - [J'ai besoin d'annuler la fusion](#jai-besoin-dannuler-la-fusion)\n    - [J'ai besoin de mettre à jour le commit parent de ma branche](#jai-besoin-de-mettre-%C3%A0-jour-le-commit-parent-de-ma-branche)\n    - [Vérifier si tous les commits d'une branche sont fusionnés](#v%C3%A9rifier-si-tous-les-commits-dune-branche-sont-fusionn%C3%A9s)\n    - [Problèmes possibles avec les rebase interactifs](#probl%C3%A8mes-possibles-avec-les-rebase-interactifs)\n      - [L'écran d'édition du rebase affiche 'noop'](#l%C3%A9cran-d%C3%A9dition-du-rebase-affiche-noop)\n      - [Il y a eu des conflits](#il-y-a-eu-des-conflits)\n  - [Remisage](#remisage)\n    - [Remiser toutes les modifications](#remiser-toutes-les-modifications)\n    - [Remiser des fichiers spécifiques](#remiser-des-fichiers-sp%C3%A9cifiques)\n    - [Remiser avec un message](#remiser-avec-un-message)\n    - [Appliquer un remisage spécifique de la liste](#appliquer-un-remisage-sp%C3%A9cifique-de-la-liste)\n  - [Rechercher](#rechercher)\n    - [Je veux rechercher une chaîne de caractères dans un commit](#je-veux-rechercher-une-cha%C3%AEne-de-caract%C3%A8res-dans-un-commit)\n    - [Je veux rechercher par auteur·trice/validateur·trice](#je-veux-rechercher-par-auteur%C2%B7tricevalidateur%C2%B7trice)\n    - [Je veux lister les commits ayant des fichiers spécifiques](#je-veux-lister-les-commits-ayant-des-fichiers-sp%C3%A9cifiques)\n    - [Trouver un tag où un commit est référencé](#trouver-un-tag-o%C3%B9-un-commit-est-r%C3%A9f%C3%A9renc%C3%A9)\n  - [Sous-modules](#sous-modules)\n    - [Cloner tous les sous-modules](#cloner-tous-les-sous-modules)\n    - [Retirer un sous-module](#retirer-un-sous-module)\n  - [Objets divers](#objets-divers)\n    - [Récupérer un fichier supprimé](#r%C3%A9cup%C3%A9rer-un-fichier-supprim%C3%A9)\n    - [Supprimer un tag](#supprimer-un-tag)\n    - [Récupérer un tag supprimé](#r%C3%A9cup%C3%A9rer-un-tag-supprim%C3%A9)\n    - [Patch supprimé](#patch-supprim%C3%A9)\n    - [Exporter un dépôt comme fichier Zip](#exporter-un-d%C3%A9p%C3%B4t-comme-fichier-zip)\n    - [Pousser une branche et un tag qui ont le même nom](#pousser-une-branche-et-un-tag-qui-ont-le-m%C3%AAme-nom)\n  - [Suivre des fichiers](#suivre-des-fichiers)\n    - [Je veux changer la capitalisation du nom d'un fichier, sans changer son contenu](#je-veux-changer-la-capitalisation-du-nom-dun-fichier-sans-changer-son-contenu)\n    - [Je veux écraser des fichiers locaux en faisant un git pull](#je-veux-%C3%A9craser-des-fichiers-locaux-en-faisant-un-git-pull)\n    - [Je veux retirer un fichier de Git mais garder le fichier](#je-veux-retirer-un-fichier-de-git-mais-garder-le-fichier)\n    - [Je veux rétablir un fichier à une version spécifique](#je-veux-r%C3%A9tablir-un-fichier-%C3%A0-une-version-sp%C3%A9cifique)\n    - [Je veux lister les changements d'un fichier spécifique entre deux commits ou branches](#je-veux-lister-les-changements-dun-fichier-sp%C3%A9cifique-entre-deux-commits-ou-branches)\n    - [Je veux que Git ignore les changements d'un fichier spécifique](#je-veux-que-git-ignore-les-changements-dun-fichier-sp%C3%A9cifique)\n  - [Paramétrage](#param%C3%A9trage)\n    - [Je veux ajouter des alias pour certaines commandes Git](#je-veux-ajouter-des-alias-pour-certaines-commandes-git)\n    - [Je veux ajouter un répertoire vide à mon dépôt](#je-veux-ajouter-un-r%C3%A9pertoire-vide-%C3%A0-mon-d%C3%A9p%C3%B4t)\n    - [Je veux mettre en cache un nom d'utilisateur et mot de passe pour un dépôt](#je-veux-mettre-en-cache-un-nom-dutilisateur-et-mot-de-passe-pour-un-d%C3%A9p%C3%B4t)\n    - [Je veux que Git ignore les changements de permissions et de filemode](#je-veux-que-git-ignore-les-changements-de-permissions-et-de-filemode)\n    - [Je veux définir un utilisateur global](#je-veux-d%C3%A9finir-un-utilisateur-global)\n  - [Je n'ai aucune idée de ce que j'ai mal fait](#je-nai-aucune-id%C3%A9e-de-ce-que-jai-mal-fait)\n- [Autres Ressources](#autres-ressources)\n  - [Livres](#livres)\n  - [Tutoriels](#tutoriels)\n  - [Scripts et Outils](#scripts-et-outils)\n  - [Clients graphiques](#clients-graphiques)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n## Dépôts\n\n### Je veux initialiser un dépôt local\n\nPour initialiser un répertoire existant comme dépôt Git :\n\n```sh\n(mon-dossier) $ git init\n```\n\n### Je veux cloner un dépôt distant\n\nPour cloner (copier) un dépôt distant, copiez l'url de ce dernier, et lancez :\n\n```sh\n$ git clone [url]\n```\n\nCeci le sauvegardera dans un dossier nommé d'après le nom du dépôt. Assurez-vous d'avoir une connexion avec le serveur distant que vous essayez de cloner (dans la plupart des cas ceci revient à s'assurer d'être connecté·e à Internet).\n\nPour le cloner vers un dossier ayant un nom différent de celui du dépôt distant :\n\n```sh\n$ git clone [url] nom-du-nouveau-dossier\n```\n\n## Éditer des Commits\n\n<a name=\"diff-last\"></a>\n### Qu'est-ce que je viens de commiter ?\n\nImaginons que vous venez tout juste d'enregistrer des changements à l'aveugle avec {code0}git commit -a{/code0} et que vous n'êtes pas sûr·e du contenu réel du commit que vous venez d'effectuer. Vous pouvez visualiser le dernier commit sur votre HEAD actuel avec :\n\n```sh\n(main)$ git show\n```\n\nOu :\n\n```sh\n$ git log -n1 -p\n```\n\nSi vous voulez voir un fichier à un commit spécifique, vous pouvez aussi faire (où `<commitid>` est le commit qui vous intéresse).\n\n```sh\n$ git show <commitid>:nomdufichier\n```\n\n<a name=\"wrong-thing-in-commit-message\"></a>\n### J'ai commis une erreur dans un message de commit\n\nSi vous vous êtes trompé·e et que le commit n'a pas encore été poussé, vous pouvez appliquer la commande suivante afin de changer le message du commit sans affecter les changements de ce même commit :\n\n```sh\n$ git commit --amend --only\n```\n\nCela ouvrira votre éditeur de texte par défaut, où vous pourrez éditer le message. Vous pouvez également effectuer la même chose en une seule commande :\n\n```sh\n$ git commit --amend --only -m 'xxxxxxx'\n```\n\nSi vous avez déjà poussé le message, vous pouvez modifier le commit et pousser de force, mais cela n'est pas recommandé.\n\n<a name=\"commit-wrong-author\"></a>\n### J'ai commit avec le mauvais nom et email dans les configurations\n\nSi c'est un commit unique, modifiez-le :\n\n```sh\n$ git commit --amend --no-edit --author \"Nouvel Auteur·trice <emaildelauteurice@mondomaine.com>\"\n```\n\nUne alternative est de configurer correctement vos paramètres d'auteur·trice avec `git config --global author.(name|email)` puis de lancer :\n\n```sh\n$ git commit --amend --reset-author --no-edit\n```\n\nSi vous avez besoin de changer tout l'historique, veuillez vous référer à la page man pour `git filter-branch`.\n\n### Je veux retirer un fichier du commit précédent\n\nPour retirer les changements effectués sur un fichier lors du précédent commit, faites la chose suivante :\n\n```sh\n$ git checkout HEAD^ monfichier\n$ git add monfichier\n$ git commit --amend --no-edit\n```\n\nDans le cas où le fichier fut introduit dans le commit et que vous voulez le retirer (de Git seul), faites :\n\n```sh\n$ git rm --cached monfichier\n$ git commit --amend --no-edit\n```\n\nCela est particulièrement utile quand vous avez un patch d'ouvert et que vous avez commité un fichier non nécessaire, et que vous avez besoin de pousser de force pour mettre à jour le patch sur le dépôt distant. L'option `--no-edit` est utilisée pour garder le message de commit existant.\n\n<a name=\"delete-pushed-commit\"></a>\n### Je veux supprimer ou retirer mon dernier commit\n\nSi vous avez besoin de supprimer des commits poussés, vous pouvez utiliser la commande suivante. Cependant, cela modifiera votre historique de manière irreversible, et mettra la pagaille dans l'historique de quiconque ayant déjà récupéré des changements depuis le dépôt distant. Pour faire court, si vous n'êtes pas sûr·e, vous ne devriez pas faire ça, jamais.\n\n```sh\n$ git reset HEAD^ --hard\n$ git push --force-with-lease [remote] [branche]\n```\n\nSi vous n'avez pas poussé, pour réinitialiser Git vers l'état dans lequel il était avant que vous ne fassiez votre dernier commit (tout en gardant vos changements) :\n\n```\n(ma-branche)$ git reset --soft HEAD^\n```\n\nCela ne marchera que si vous n'avez pas poussé. Si vous avez poussé, la seule vraie chose sécurisée à faire est `git revert SHAduMauvaisCommit`. Cela créera un nouveau commit qui annule tous les changements du commit en question. Ou, si la branche vers laquelle vous avez poussé est \"rebase-safe\" (en d'autres termes, les autres développeur·euse·s ne la récupéreront pas), vous pouvez juste lancer `git push --force-with-lease`. Pour plus d'informations, jetez un œil [à la section ci-dessus](#je-veux-supprimer-ou-retirer-mon-dernier-commit).\n\n<a name=\"delete-any-commit\"></a>\n### Supprimer/retirer un commit arbitraire\n\nLe même avertissement que ci-dessus s'applique. Ne faites jamais cela si possible.\n\n```sh\n$ git rebase --onto SHA1_DU_MAUVAIS_COMMIT^ SHA1_DU_MAUVAIS_COMMIT\n$ git push --force-with-lease [remote] [branche]\n```\n\nOu faites un [rebase interactif](#interactive-rebase) et retirez les lignes correspondantes au(x) commit(s) que vous souhaitez supprimer.\n\n<a name=\"force-push\"></a>\n### J'ai essayé de pousser un commit modifié vers le dépôt distant, mais j'ai eu un message d'erreur\n\n```sh\nTo https://github.com/votrenomdutilisateur/repo.git\n! [rejected]        ma-branche -> ma-branche (non-fast-forward)\nerror: failed to push some refs to 'https://github.com/tanay1337/webmaker.org.git'\nhint: Updates were rejected because the tip of your current branch is behind\nhint: its remote counterpart. Integrate the remote changes (e.g.\nhint: 'git pull ...') before pushing again.\nhint: See the 'Note about fast-forwards' in 'git push --help' for details.\n```\n\nNotez que, tout comme avec un rebase (voir ci-dessous), le fait de modifier **remplace l'ancien commit avec un nouveau**, donc vous devez pousser de force (`--force-with-lease`) vos changements si vous avez déjà poussé le commit vers votre dépôt distant avant sa modification. Soyez prudent·e quand vous faites cela : Assurez vous de *toujours* spécifier une branche !\n\n```sh\n(ma-branche)$ git push origin ma-branche --force-with-lease\n```\n\nEn règle générale, **évitez de pousser de force**. Il est préférable de créer et pousser un nouveau commit plutôt que de pousser de force un commit modifié car cela causera des conflits dans l'historique pour n'importe quel développeur·euse ayant déjà intéragit avec la branche en question ou quelque branche fille. `--force-with-lease` échouera toujours, si quelqu'un d'autre était déjà en train de travailler sur la même branche que vous et que votre push réécrirait par-dessus ces modifications.\n\nSi vous êtes *absolument* sûr·e que personne n'est en train de travailler sur la même branche que vous ou que vous souhaitez mettre à jour la branche de manière *inconditionnelle*, vous pouvez utiliser `--force` (`-f`), mais cela devrait être évité en général.\n\n<a name=\"undo-git-reset-hard\"></a>\n### J'ai fait un hard reset par accident, et je veux retrouver mes changements\n\nSi vous avez accidentellement fait un `git reset --hard`, vous pouvez normalement retrouver votre commit, car Git garde un log de tout ce que vous faites pendant quelques jours.\n\nÀ noter : Cela n'est valide que si votre travail est sauvegardé, c'est à dire dans un commit ou un remisage. `git reset --hard` *supprimera* les modifications non commitées, donc utilisez cela avec précaution (une option plus sûre est `git reset --keep`).\n\n```sh\n(main)$ git reflog\n```\n\nVous verrez une liste de vos précédents commits, et un commit pour la réinitialisation. Choisissez le SHA du commit vers lequel vous souhaitez retourner, et réinitialisez à nouveau :\n\n```sh\n(main)$ git reset --hard SHA1234\n```\n\nEt cela devrait faire l'affaire.\n\n<a name=\"undo-a-commit-merge\"></a>\n### J'ai commité et poussé une fusion par accident\n\nSi vous avez accidentellement fusionné une branche d'une fonctionnalité avec la branche de développement principale avant qu'elle ne soit prête à être fusionnée, vous pouvez toujours annuler cette fusion. Mais il y a un piège : un commit de fusion a plus d'un parent (en général deux).\n\nUtilisez cette commande :\n\n```sh\n(feature-branch)$ git revert -m 1 <commit>\n```\noù l'option `-m 1` demande de sélectionner le parent numéro 1 (la branche vers laquelle la fusion a été faite) comme parent vers lequel annuler la fusion.\n\nÀ noter : le numéro du parent n'est pas un identifiant de commit. Un commit de fusion ressemble plus à `Merge: 8e2ce2d 86ac2e7`. Le numéro du parent est l'index basé sur 1 du parent souhaité sur cette ligne, le premier identifiant est le numéro 1, le second le numéro 2, et ainsi de suite.\n\n<a name=\"undo-sensitive-commit-push\"></a>\n### J'ai commité et poussé des fichiers contenant des données sensibles par accident\n\nSi vous avez accidentellement poussé des fichiers contenant des données sensibles (mots de passe, clés, etc.), vous pouvez modifier le commit précédent. Gardez toutefois à l'esprit qu'une fois que vous avez poussé un commit, vous devez considérer n'importe quelle donnée qu'il contient comme étant compromise. Ces étapes peuvent supprimer les données sensibles de votre dépôt public ou de votre copie locale, mais vous ne **pouvez pas** supprimer les données sensibles des copies clonées par d'autres personnes. Si vous avez commité un mot de passe, **changez-le immédiatement**. Si vous avez commité une clé, **révoquez-la et régénérez-la immédiatement**. Modifier le commit poussé n'est pas suffisant, étant donné que n'importe qui aurait pu extraire le commit original contenant vos données sensibles pendant ce temps.\n\nSi vous souhaitez modifier le fichier et supprimer les données sensibles, lancez :\n```sh\n(feature-branch)$ git add fichier_modifié\n(feature-branch)$ git commit --amend --no-edit\n(feature-branch)$ git push --force-with-lease origin [branche]\n```\n\nSi vous souhaitez supprimer tout un fichier (mais le garder en local), lancez :\n```sh\n(feature-branch)$ git rm --cached fichier_sensible\necho fichier_sensible >> .gitignore\n  (feature-branch)$ git add .gitignore\n(feature-branch)$ git commit --amend --no-edit\n(feature-branch)$ git push --force-with-lease origin [branche]\n```\nAlternativement, stockez vos données sensibles dans des variables d'environnement locales.\n\nSi vous souhaitez supprimer tout un fichier (et ne pas le garder en local), lancez :\n```sh\n(feature-branch)$ git rm fichier_sensible\n(feature-branch)$ git commit --amend --no-edit\n(feature-branch)$ git push --force-with-lease origin [branche]\n```\n\nSi vous avez créé d'autres commits pendant ce temps (c'est à dire que les données sensibles sont dans un commit avant le commit précédent), vous devrez utiliser la fonction `rebase`.\n\n## Indexation\n\n<a name=\"add-staged-changes-to-previous-commit\"></a>\n### J'ai besoin d'ajouter des modifications indexées sur le commit précédent\n\n```sh\n(ma-branche*)$ git commit --amend\n```\n\nSi vous savez déjà que vous ne souhaitez pas modifier le message du commit, vous pouvez dire à Git de réutiliser ce dernier :\n\n```sh\n(ma-branche*)$ git commit --amend -C HEAD\n```\n\n\n<a name=\"commit-partial-new-file\"></a>\n### Je veux indexer une partie d'un fichier, mais pas tout le fichier\n\nNormalement, quand vous souhaitez modifier une partie d'un fichier, il faut lancer ceci :\n\n```sh\n$ git add --patch nomdufichier.x\n```\n\n`-p` fonctionnera comme raccourci. Cela ouvrira le mode interactif. Vous serez en mesure d'utiliser l'option `s` pour séparer le commit. Cependant, si le fichier est nouveau, vous n'aurez pas cette option. Pour ajouter un nouveau fichier, faites comme ceci :\n\n```sh\n$ git add -N nomdufichier.x\n```\n\nEnsuite, vous devrez utiliser l'option `e` afin de choisir manuellement quelles lignes ajouter. Lancer `git diff --cached` ou `git diff --staged` vous montrera quelles lignes vous avez indexées comparées à celles qui sont toujours sauvegardées en local.\n\n<a name=\"stage-in-two-commits\"></a>\n### Je veux ajouter les changements d'un fichier dans deux commits différents\n\n`git add` ajoutera le fichier entier à un commit. `git add -p` vous permettra de sélectionner interactivement quels changements vous souhaitez ajouter.\n\n<a name=\"unstaging-edits-and-staging-the-unstaged\"></a>\n### Je veux indexer mes modifications indexées, et désindexer mes modifications indexées\n\nCela est délicat. La meilleure chose que nous pouvons vous conseiller est que vous devriez remiser vos modifications non indexées, puis utiliser `git reset`. Après cela, utilisez `pop` pour déremiser vos modifications, puis ajoutez-les :\n\n```sh\n$ git stash -k\n$ git reset --hard\n$ git stash pop\n$ git add -A\n```\n\n## Modifications non indexées\n\n<a name=\"move-unstaged-edits-to-new-branch\"></a>\n### Je veux déplacer mes modifications non indexées vers une nouvelle branche\n\n```sh\n$ git checkout -b ma-branche\n```\n\n<a name=\"move-unstaged-edits-to-old-branch\"></a>\n### Je veux déplacer mes modifications non indexées vers une branche différente existante\n\n```sh\n$ git stash\n$ git checkout ma-branche\n$ git stash pop\n```\n\n<a name=\"discard-local-uncommitted-changes\"></a>\n### Je veux me débarrasser de mes modifications locales non commitées (indexées et non-indexées)\n\nSi vous voulez vous débarrasser de toutes vos modifications locales indexées et non-indexées, vous pouvez faire ceci :\n\n```sh\n(ma-branche)$ git reset --hard\n# ou\n(main)$ git checkout -f\n```\n\nCette commande désindexera tous les fichiers que vous avez pu indexer avec `git add` :\n\n```sh\n$ git reset\n```\n\nCette commande annulera toutes les modifications locales non commitées (elle devrait être exécutée à la racine du dépôt) :\n\n```sh\n$ git checkout .\n```\n\nVous pouvez également annuler les changements non commités d'un fichier ou d'un dossier en particulier :\n\n```sh\n$ git checkout [un_dossier|fichier.txt]\n```\n\nIl existe également une autre façon d'annuler toutes vos modifications non commitées (plus longue à taper, mais fonctionne depuis n'importe quel sous-dossier) :\n\n```sh\n$ git reset --hard HEAD\n```\n\nCette commande supprimera tous les fichiers locaux non indexés, afin que seuls les fichiers suivis par Git ne restent :\n\n```sh\n$ git clean -fd\n```\n\n`-x` supprimera également tous les fichiers ignorés.\n\n### Je veux me débarrasser de modifications non-indexées spécifiques\n\nQuand vous souhaitez vous débarrasser de quelques modifications dans votre copie de travail, mais pas toutes, faites un `checkout` sur les modifications non désirées, et gardez les bonnes :\n\n```sh\n$ git checkout -p\n# Répondez y à tous les bouts de code que vous souhaitez jeter\n```\n\nUne autre stratégie implique d'utiliser `stash`. Remisez toutes les bonnes modifications, réinitialisez votre copie locale, et réappliquez les bonnes modifications :\n\n```sh\n$ git stash -p\n# Sélectionnez tous les bouts de code que vous souhaitez garder\n$ git reset --hard\n$ git stash pop\n```\n\nAlternativement, remisez vos changements non désirés, puis jetez le stash :\n\n```sh\n$ git stash -p\n# Sélectionnez tous les bouts de code que vous ne souhaitez pas sauvegarder\n$ git stash drop\n```\n\n### Je veux me débarrasser de fichiers non-indexés spécifiques\n\nQuand vous souhaitez vous débarrasser d'un fichier en particulier de votre copie de travail :\n\n```sh\n$ git checkout monFichier\n```\n\nAlternativement, pour vous débarrasser de plusieurs fichiers dans votre copie locale, listez chacun d'entre eux :\n\n```sh\n$ git checkout monPremierFichier monDeuxiemeFichier\n```\n\n### Je veux me débarrasser de mes modifications locales non-indexées uniquement\n\nQuand vous souhaitez vous débarrasser de toutes vos modifications locales non commitées :\n\n```sh\n$ git checkout .\n```\n<a name=\"discard-all-untracked-files\"></a>\n### Je veux me débarrasser de tous mes fichiers non suivis\n\nQuand vous souhaitez vous débarrasser de tous vos fichiers non suivis :\n\n```sh\n$ git clean -f\n```\n\n<a name=\"unstage-specific-staged-file\"></a>\n### Je veux désindexer un fichier indexé spécifique\n\nIl arrive parfois que nous ayons un ou plusieurs fichiers qui ont été indexés par accident. Et ces fichiers n'ont pas été commités auparavant. Pour les désindexer :\n\n```sh\n$ git reset -- <nomdufichier>\n```\n\nCela entraînera la désindexation du fichier et le remettra à son état non suivi.\n\n## Branches\n\n### Je veux lister toutes les branches\n\nPour lister les branches locales :\n\n```sh\n$ git branch\n```\n\nPour lister les branches distantes :\n\n```sh\n$ git branch -r\n```\n\nPour lister toutes les branches (à la fois locales et distantes) :\n\n```sh\n$ git branch -a\n```\n\n<a name=\"create-branch-from-commit\"></a>\n### Créer une branche à partir d'un commit\n```sh\n$ git checkout -b <branche> <SHA1_DU_COMMIT>\n```\n\n<a name=\"pull-wrong-branch\"></a>\n### J'ai pull depuis/vers la mauvaise branche\n\nC'est une autre occasion d'utiliser `git reflog` afin de voir où votre HEAD pointait avant le mauvais `pull` :\n\n```sh\n(main)$ git reflog\nab7555f HEAD@{0}: pull origin wrong-branch: Fast-forward\nc5bc55a HEAD@{1}: checkout: checkout message goes here\n```\n\nRéinitialisez simplement votre branche vers le commit désiré :\n\n```sh\n$ git reset --hard c5bc55a\n```\n\nEt voilà.\n\n<a name=\"discard-local-commits\"></a>\n### Je veux supprimer mes commits locaux afin que ma branche soit pareille à celle sur le serveur\n\nAssurez-vous que vous n'avez pas poussé vos modifications sur le serveur.\n\n`git status` devrait vous indiquer combien de commits en avance vous êtes par rapport à origin :\n\n```sh\n(ma-branche)$ git status\n# On branch ma-branche\n# Your branch is ahead of 'origin/my-branch' by 2 commits.\n#   (use \"git push\" to publish your local commits)\n#\n```\n\nUne des façons de faire pour réinitialiser votre branche afin qu'elle corresponde à origin (afin d'avoir la même chose que le dépôt distant) est de lancer ceci :\n\n```sh\n(ma-branche)$ git reset --hard origin/ma-branche\n```\n\n<a name=\"commit-wrong-branch\"></a>\n### J'ai commité sur main au lieu d'une nouvelle branche\n\nCréez la nouvelle branche tout en restant sur main :\n\n```sh\n(main)$ git branch ma-branche\n```\n\nRéinitialisez la branche main vers le commit précédent :\n\n```sh\n(main)$ git reset --hard HEAD^\n```\n\n`HEAD^` est un raccourci pour `HEAD^1`. Cela indique le premier parent de `HEAD`, de la même façon que `HEAD^2` indique le second parent du commit (des fusions peuvent avoir deux parents).\n\nNotez que `HEAD^2` ne signifie **pas** la même chose que `HEAD~2` (visitez [ce lien](http://www.paulboxley.com/blog/2011/06/git-caret-and-tilde) pour plus d'informations).\n\nAlternativement, si vous ne souhaitez pas utiliser `HEAD^`, retrouvez le hash du commit vers lequel vous souhaitez remettre votre branche main (`git log` devrait faire l'affaire). Puis réinitialisez vers ce hash. `git push` s'assurera que la modification est reflétée sur le serveur distant.\n\nPar exemple, si le hash du commit sur lequel votre branche main est supposée être est `a13b85e` :\n\n```sh\n(main)$ git reset --hard a13b85e\nHEAD is now at a13b85e\n```\n\nDéplacez-vous vers la nouvelle branche pour continuer de travailler :\n\n```sh\n(main)$ git checkout ma-branche\n```\n\n<a name=\"keep-whole-file\"></a>\n### Je veux séparer tout un fichier d'un autre ref-ish\n\nAdmettons que vous avez un pic de travail (voir la note), avec des centaines de changements. Tout fonctionne bien. Maintenant, vous commitez vers une autre branche pour sauvegarder ce travail :\n\n```sh\n(solution)$ git add -A && git commit -m \"Ajout de tous les changements de ce pic vers un gros commit.\"\n```\n\nQuand vous souhaitez mettre tout cela vers une branche (d'une fonctionnalité ou `develop`), ce qui vous intéresse est de garder les fichiers dans leur entièreté. Vous voudriez également séparer votre gros commit en plusieurs petits commits.\n\nAdmettons que vous ayez :\n\n  * La branche `solution`, avec la solution à votre pic. En avance d'un commit par rapport à `develop`.\n  * La branche `develop`, où vous souhaitez ajouter vos modifications.\n\nVous pouvez résoudre cela en ramenant les contenus vers votre branche :\n\n```sh\n(develop)$ git checkout solution -- fichier1.txt\n```\n\nCela ramènera le contenu de ce fichier dans la branche `solution` vers votre branche `develop` :\n\n```sh\n# On branch develop\n# Your branch is up-to-date with 'origin/develop'.\n# Changes to be committed:\n#  (use \"git reset HEAD <file>...\" to unstage)\n#\n#        modified:   fichier1.txt\n```\n\nPuis, commitez comme d'habitude.\n\nNote: Les pics de solutions servent à analyser ou résoudre un problème. Ces solutions sont ensuite utilisées afin d'avoir une estimation puis jetées une fois que tout le monde a une vision claire du problème. ~ [Wikipedia](https://en.wikipedia.org/wiki/Extreme_programming_practices).\n\n<a name=\"cherry-pick\"></a>\n### J'ai fait plusieurs commits sur une même branche qui auraient dû être sur plusieurs branches\n\nAdmettons que vous êtes sur votre branche main. En lançant `git log`, vous remarquez que vous avez fait deux commits :\n\n```sh\n(main)$ git log\n\ncommit e3851e817c451cc36f2e6f3049db528415e3c114\nAuthor: Alex Lee <alexlee@example.com>\nDate:   Tue Jul 22 15:39:27 2014 -0400\n\n    Bug #21 - Ajout de la protection CSRF\n\ncommit 5ea51731d150f7ddc4a365437931cd8be3bf3131\nAuthor: Alex Lee <alexlee@example.com>\nDate:   Tue Jul 22 15:39:12 2014 -0400\n\n    Bug #14 - Correction de l'espacement du titre\n\ncommit a13b85e984171c6e2a1729bb061994525f626d14\nAuthor: Aki Rose <akirose@example.com>\nDate:   Tue Jul 21 01:12:48 2014 -0400\n\n    Premier commit\n```\n\nNotons dans un coin les hashes des commits pour chaque bug (`e3851e8` pour le #21, `5ea5173` pour le #14).\n\nPour commencer, réinitialisons notre branche main sur le bon commit (`a13b85e`) :\n\n```sh\n(main)$ git reset --hard a13b85e\nHEAD is now at a13b85e\n```\n\nMaintenant, nous pouvons créer une nouvelle branche pour le bug #21 :\n\n```sh\n(main)$ git checkout -b 21\n(21)$\n```\n\nMaintenant, faisons un `cherry-pick` du commit pour le bug #21 par-dessus notre branche. Cela signifie que nous appliquerons ce commit, et seulement ce commit, directement au-dessus de ce qui se trouve sur notre HEAD :\n\n```sh\n(21)$ git cherry-pick e3851e8\n```\n\nLors de cette étape, il est possible qu'il y ait des conflits. Regardez la section [**Il y a eu des conflits**](#merge-conflict) dans la section [faire un rebase interactif](#interactive-rebase) ci-dessus pour savoir comment résoudre ces conflits.\n\nMaintenant, créons une nouvelle branche pour le bug #14, aussi basée sur main :\n\n```sh\n(21)$ git checkout main\n(main)$ git checkout -b 14\n(14)$\n```\n\nEt pour finir, faisons un `cherry-pick` du commit pour le bug #14 :\n\n```sh\n(14)$ git cherry-pick 5ea5173\n```\n\n<a name=\"delete-stale-local-branches\"></a>\n### Je veux supprimer mes branches locales qui ont été supprimée sur le dépôt distant\nUne fois que vous avez accepté une Pull Request sur GitHub, vous avez l'option de supprimer la branche fusionnée dans votre fork. Si vous ne prévoyez pas de continuer à travailler sur la branche, cela est plus propre de supprimer les copies locales de la branche afin de ne pas encombrer votre copie de travail avec un tas de branches obsolètes.\n\n```sh\n$ git fetch -p upstream\n```\n\noù `upstream` est le dépôt distant depuis lequel vous voulez mettre à jour.\n\n<a name=\"restore-a-deleted-branch\"></a>\n### J'ai supprimé ma branche par accident\n\nSi vous poussez régulièrement sur la branche distante, vous devriez ne pas avoir de problème la plupart du temps. Mais il arrive parfois que vous finissez par supprimer vos branches. Admettons que nous créons une nouvelle branche avec un nouveau fichier :\n\n```sh\n(main)$ git checkout -b ma-branche\n(ma-branceh)$ git branch\n(ma-branche)$ touch foo.txt\n(ma-branche)$ ls\nREADME.md foo.txt\n```\n\nAjoutons cela et commitons :\n\n```sh\n(ma-branche)$ git add .\n(ma-branche)$ git commit -m 'ajout de foo.txt'\n(ma-branche)$ ajout de foo.txt\n 1 files changed, 1 insertions(+)\n create mode 100644 foo.txt\n(ma-branche)$ git log\n\ncommit 4e3cd85a670ced7cc17a2b5d8d3d809ac88d5012\nAuthor: siemiatj <siemiatj@example.com>\nDate:   Wed Jul 30 00:34:10 2014 +0200\n\n    ajout de foo.txt\n\ncommit 69204cdf0acbab201619d95ad8295928e7f411d5\nAuthor: Kate Hudson <katehudson@example.com>\nDate:   Tue Jul 29 13:14:46 2014 -0400\n\n    Correction #6: Push de force après avoir édité les commits\n```\n\nMaintenant, revenons sur main et supprimons notre branche \"par accident\" :\n\n```sh\n(ma-branche)$ git checkout main\nSwitched to branch 'main'\nYour branch is up-to-date with 'origin/main'.\n(main)$ git branch -D my-branch\nDeleted branch ma-branche (was 4e3cd85).\n(main)$ echo oh non, j'ai supprimé ma branche !\noh non, j'ai supprimé ma branche !\n```\n\nÀ cette étape, vous devriez devenir familier avec `reflog`, un logueur amélioré. Il stocke l'historique de toutes les actions dans le dépôt :\n\n```\n(main)$ git reflog\n69204cd HEAD@{0}: checkout: moving from ma-branche to main\n4e3cd85 HEAD@{1}: commit: ajout de foo.txt\n69204cd HEAD@{2}: checkout: moving from main to ma-branche\n```\n\nComme vous pouvez le remarquer, nous avons le hash du commit de notre branche supprimée. Voyons voir si nous pouvons restaurer notre branche supprimée.\n\n```sh\n(main)$ git checkout -b ma-branche-help\nSwitched to a new branch 'ma-branche-help'\n(ma-branche-help)$ git reset --hard 4e3cd85\nHEAD is now at 4e3cd85 ajout de foo.txt\n(ma-branche-help)$ ls\nREADME.md foo.txt\n```\n\nVoilà ! Nous avons récupéré notre fichier supprimé. `git reflog` est aussi utile quand un rebase se passe terriblement mal.\n\n### Je veux supprimer une branche\n\nPour supprimer une branche distante :\n\n```sh\n(main)$ git push origin --delete ma-branche\n```\n\nVous pouvez aussi faire :\n\n```sh\n(main)$ git push origin :ma-branche\n```\n\nPour supprimer une branche locale :\n\n```sh\n(main)$ git branch -d ma-branche\n```\n\nPour supprimer une branche locale qui *n'a pas* été fusionnée vers la branche actuelle ou une branche distante :\n\n```sh\n(main)$ git branch -D ma-branche\n```\n\n### Je veux supprimer plusieurs branches\n\nAdmettons que vous voulez supprimer toutes les branches qui commencent par `fix/` :\n\n```sh\n(main)$ git branch | grep 'fix/' | xargs git branch -d\n```\n\n### Je veux renommer une branche\n\nJe veux renommer la branche actuelle (locale) :\n\n```sh\n(main)$ git branch -m nouveau-nom\n```\n\nPour renommer une autre branche (locale) :\n\n```sh\n(main)$ git branch -m ancien-nom nouveau-nom\n```\n\n<a name=\"working-on-checkout-remote-branch\"></a>\n### Je veux me déplacer sur une branche distante sur laquelle quelqu'un est en train de travailler\n\nPour commencer, récupérez toutes les branches depuis le dépôt distant :\n\n```sh\n(main)$ git fetch --all\n```\n\nAdmettons que vous souhaitez vous déplacer sur `daves` depuis le dépôt distant :\n\n```sh\n(main)$ git checkout --track origin/daves\nBranch daves set up to track remote branch daves from origin.\nSwitched to a new branch 'daves'\n```\n\n(`--track` est un raccourci pour `git checkout -b [branch] [remotename]/[branch]`)\n\nCela vous donnera une copie locale de la branche `daves`, et n'importe quelle mise à jour qui y sera poussée sera aussi visible sur le dépôt distant.\n\n### Je veux créer une nouvelle branche distante à partir de celle en locale\n\n```sh\n$ git push <remote> HEAD\n```\n\nSi vous voulez configurer cette branche distante en tant qu'upstream pour la branche actuelle, lancez la commande suivante à la place :\n\n```sh\n$ git push -u <remote> HEAD\n```\n\nAvec le mode `upstream` et le mode `simple` (défaut dans Git 2.0) de la configuration de `push.default`, la commande suivante poussera la branche actuelle par rapport à la branche distante qui a été précédemment enregistrée avec `-u` :\n\n```sh\n$ git push\n```\n\nLe comportement des autres modes de `git push` est détaillé dans la [documentation de `push.default`](https://git-scm.com/docs/git-config#Documentation/git-config.txt-pushdefault).\n\n### Je veux configurer une branche distante en tant qu'upstream pour une branche locale\n\nVous pouvez configurer une branche distante en tant qu'upstream pour la branche locale actuelle en utilisant :\n\n```sh\n$ git branch --set-upstream-to [nomduremote]/[branche]\n# ou, en utilisant le raccourci :\n$ git branch -u [nomduremote]/[branche]\n```\n\nPour configurer la branche distante en tant qu'upstream pour une autre branche locale :\n\n```sh\n$ git branch -u [nomduremote]/[branche] [branche-locale]\n```\n\n<a name=\"head-to-track-remote-branch\"></a>\n### Je veux configurer mon HEAD pour suivre la branche distante par défaut\n\nEn vérifiant vos branches distantes, vous pouvez voir lesquelles d'entre-elles sont suivies par HEAD. Dans certains cas, ce n'est pas la branche désirée.\n\n```sh\n$ git branch -r\n  origin/HEAD -> origin/gh-pages\n  origin/main\n```\n\nPour changer cela afin que `origin/HEAD` suive `origin/main`, vous pouvez lancer cette commande :\n\n```sh\n$ git remote set-head origin --auto\norigin/HEAD set to main\n```\n\n### J'ai fait des modifications sur la mauvaise branche\n\nSi vous avez fait des modifications non commitées et réalisez par la suite que vous êtes sur la mauvaise branche, remisez les modifications et appliquez-les sur la branche que vous voulez :\n\n```sh\n(mauvaise_branche)$ git stash\n(mauvaise_branche)$ git checkout <bonne_branche>\n(bonne_branche)$ git stash apply\n```\n\n## Rebaser et fusionner\n\n<a name=\"undo-rebase\"></a>\n### Je veux annuler un rebase/merge\n\nIl se peut que vous avez fait une fusion ou un rebase sur votre branche actuelle avec une mauvaise branche, ou que vous vous êtes perdus ou n'arrivez pas à finir le processus de rebase ou de fusion. Git sauvegarde le pointeur de HEAD original dans une variable appelée ORIG_HEAD avant de faire des opérations dangereuses, afin qu'il soit plus facile de réinitialiser votre branche dans l'état avant le rebase ou la fusion :\n\n```sh\n(ma-branche)$ git reset --hard ORIG_HEAD\n```\n\n<a name=\"force-push-rebase\"></a>\n### J'ai rebase, mais je ne veux pas pousser de force\n\nMalheureusement, vous devez pousser de force si vous souhaitez que ces modifications soient répercutées sur la branche distante. C'est parce que vous avez changé l'historique. La branche distante n'acceptera pas les modifications, sauf si vous poussez de force. C'est l'une des principales raisons pour lesquelles de nombreuses personnes utilisent un flux de travail à base de fusions plutôt qu'un flux de travail à base de rebase : les grandes équipes peuvent avoir des problèmes avec les développeurs qui poussent de force. Utilisez ceci avec prudence. Une façon plus sûre d'utiliser rebase est de ne pas du tout refléter vos modifications sur la branche distante, mais plutôt de procéder de la manière suivante :\n\n```sh\n(main)$ git checkout ma-branche\n(ma-branche)$ git rebase -i main\n(ma-branche)$ git checkout main\n(main)$ git merge --ff-only ma-branche\n```\n\nPour plus d'informations, visitez [ce thread de SO](https://stackoverflow.com/questions/11058312/how-can-i-use-git-rebase-without-requiring-a-forced-push).\n\n<a name=\"interactive-rebase\"></a>\n### J'ai besoin de combiner des commits\n\nAdmettons que vous êtes en train de travailler sur une branche qui sera ou est dans une demande de fusion vers `main`. Dans le cas le plus simple, il suffit de combiner *tous* vos commits en un seul et vous vous fichez des timestamps des commits, vous pouvez faire un reset et recommiter. Assurez-vous que la branche main est à jour et que toutes vos modifications sont commitées, puis faites :\n\n```sh\n(ma-branche)$ git reset --soft main\n(ma-branche)$ git commit -am \"Nouvelle fonctionnalité géniale\"\n```\n\nSi vous voulez plus de contrôle, et également conserver les timestamps, vous devez faire ce qu'on appelle un rebase interactif :\n\n```sh\n(ma-branche)$ git rebase -i main\n```\n\nSi vous ne travaillez pas par rapport à une autre branche, vous allez devoir `rebase` relativement à votre `HEAD`. Si vous voulez combiner les 2 derniers commits par exemple, vous allez devoir `rebase` par rapport à `HEAD~2`. Pour les 3 derniers, `HEAD~3`, etc.\n\n```sh\n(main)$ git rebase -i HEAD~2\n```\n\nAprès avoir lancé votre commande `rebase`, vous verrez quelque chose dans le genre dans votre éditeur de texte :\n\n```vim\npick a9c8a1d Un peu de refactor\npick 01b2fd8 Nouvelle feature génial\npick b729ad5 fixup\npick e3851e8 autre fix\n\n# Rebase 8074d12..b729ad5 onto 8074d12\n#\n# Commands:\n#  p, pick = use commit\n#  r, reword = use commit, but edit the commit message\n#  e, edit = use commit, but stop for amending\n#  s, squash = use commit, but meld into previous commit\n#  f, fixup = like \"squash\", but discard this commit's log message\n#  x, exec = run command (the rest of the line) using shell\n#\n# These lines can be re-ordered; they are executed from top to bottom.\n#\n# If you remove a line here THAT COMMIT WILL BE LOST.\n#\n# However, if you remove everything, the rebase will be aborted.\n#\n# Note that empty commits are commented out\n```\n\nToutes les lignes commençant par un `#` sont des commentaires, elles n'affecteront pas votre rebase.\n\nVous devez ensuite remplacer les commandes `pick` avec n'importe laquelle parmi celles présentes dans la liste ci-dessus, et vous pouvez également supprimer des commits en supprimant les lignes correspondantes.\n\nPar exemple, si vous voulez **laisser le commit le plus vieux (le premier) tel quel et combiner tous les commits suivants avec le deuxième plus vieux**, vous devez remplacer les lettres à côté de chaque commit sauf le premier et le deuxième par un `f` :\n\n```vim\npick a9c8a1d Un peu de refactor\npick 01b2fd8 Nouvelle feature géniale\nf b729ad5 fixup\nf e3851e8 autre fix\n```\n\nSi vous voulez combiner ces commits **et renommer le commit**, il vous faudra ajouter un `r` à côté du deuxième commit ou utiliser simplement `s` au lieu de `f` :\n\n```vim\npick a9c8a1d Un peu de refactor\npick 01b2fd8 Nouvelle feature géniale\ns b729ad5 fixup\ns e3851e8 autre fix\n```\n\nVous pouvez ensuite renommer le commit dans le prochain éditeur de texte qui s'affiche :\n\n```vim\nNouvelles fonctionnalités encore plus géniales\n\n# Please enter the commit message for your changes. Lines starting\n# with '#' will be ignored, and an empty message aborts the commit.\n# rebase in progress; onto 8074d12\n# You are currently editing a commit while rebasing branch 'main' on '8074d12'.\n#\n# Changes to be committed:\n#   modified:   README.md\n#\n\n```\n\nSi tout se passe bien, vous devriez voir quelque chose comme ceci :\n\n```sh\n(main)$ Successfully rebased and updated refs/heads/main.\n```\n\n#### Stratégie de fusion sûre\n`--no-commit` fait une fusion mais prétend que la fusion a échoué et ne commit pas automatiquement, laissant la chance à l'utilisateur d'inspecter plus et de bidouiller plus les résultats de la fusion avant de commiter. `no-ff` garde une preuve qu'une branche de fonctionnalité a auparavant existé, gardant ainsi l'historique du projet consistant :\n\n```sh\n(main)$ git merge --no-ff --no-commit ma-branche\n```\n\n#### J'ai besoin de fusionner deux branches en un seul commit\n\n```sh\n(main)$ git merge --squash ma-branche\n```\n\n<a name=\"rebase-unpushed-commits\"></a>\n#### Je veux combiner les commits non poussés uniquement\n\nParfois, vous avez plusieurs commits en cours que vous souhaitez combiner avant de les pousser sur l'upstream. Vous ne voulez pas combiner des commits qui ont déjà été poussés sur l'upstream par accident, car quelqu'un d'autre a peut-être déjà effectué des commits qui y font référence :\n\n```sh\n(main)$ git rebase -i @{u}\n```\n\nCela fera un rebase interactif que liste seulement les commits que vous n'avez pas poussé, afin que cela soit plus sûr de réordonner/corriger/combiner n'importe lesquels de la liste.\n\n#### J'ai besoin d'annuler la fusion\n\nParfois, une fusion peux produire des problèmes pour certains fichiers. Dans ces cas là, nous pouvons utiliser l'option `abort` afin d'abonner le processus de résolution de conflits en cours, afin d'essayer de reconstruire l'état qu'on avait avant la fusion :\n\n```sh\n(ma-branche)$ git merge --abort\n```\n\nCette commande est disponible dans Git depuis les versions >= 1.7.4\n\n### J'ai besoin de mettre à jour le commit parent de ma branche\n\nAdmettons que vous avez une branche main, une branche feature-1 créée à partir de main, et une branche feature-2 créée à partir de feature-1, puis que le commit parent de feature-2 n'est plus le bon (il devrait être celui correspondant au HEAD de feature-1, étant donné que notre branche a été créée à partir de celui-ci). Vous pouvez réparer ça avec `git rebase --onto` :\n\n```sh\n(feature-2)$ git rebase --onto feature-1 <le premier commit dans votre branche feature-2 que vous ne voulez pas ramene> feature-2\n```\n\nCela peut vous venir en aide dans les situations délicates où vous avez une fonctionnalité créée sur la base d'une autre fonctionnalité qui n'a pas encore été fusionnée, et qu'une correction de bug sur la branche feature-1 a besoin d'être reflétée sur votre branche feature-2.\n\n### Vérifier si tous les commits d'une branche sont fusionnés\n\nPour vérifier si tous les commits d'une branche sont fusionnés sur une autre branche, vous devriez comparer les HEAD (ou n'importe quel autre commit) de ces branches :\n\n```sh\n(main)$ git log --graph --left-right --cherry-pick --oneline HEAD...feature/120-on-scroll\n```\n\nCela vous dira si des commits sont dans l'une mais pas dans l'autre, et vous donnera une liste de tout ce qui n'est pas commun aux deux branches. Une alternative est de faire ceci :\n\n```sh\n(main)$ git log main ^feature/120-on-scroll --no-merges\n```\n\n### Problèmes possibles avec les rebase interactifs\n\n<a name=\"noop\"></a>\n#### L'écran d'édition du rebase affiche 'noop'\n\nSi vous voyez cela :\n```\nnoop\n```\n\nCela signifie que vous êtes en train de rebaser par rapport à une branche qui a un commit identique, ou qui est *en avance* par rapport à votre branche actuelle. Vous pouvez essayer :\n\n* de vous assurez que votre branche main est là où elle devrait être\n* de rebaser par rapport à `HEAD~2` ou plus tôt à la place\n\n<a name=\"merge-conflict\"></a>\n#### Il y a eu des conflits\n\nSi vous n'êtes pas en mesure de terminer le rebase avec succès, vous allez peut-être devoir résoudre des conflits.\n\nPour commencer, lancez `git status` afin de voir quels fichiers ont des conflits :\n\n```sh\n(ma-branche)$ git status\nOn branch ma-branche\nChanges not staged for commit:\n  (use \"git add <file>...\" to update what will be committed)\n  (use \"git checkout -- <file>...\" to discard changes in working directory)\n\n  both modified:   README.md\n```\n\nDans cet exemple, `README.md` a des conflits. Ouvrez le fichier et cherchez la chose suivante :\n\n```vim\n   <<<<<<< HEAD\n   some code\n   =========\n   some code\n   >>>>>>> nouveau-commit\n```\n\nVous aurez besoin de résoudre les différences entre le code qui fut ajouté dans votre nouveau commit (dans cet exemple, tout ce qu'il y a entre la ligne du milieu et `nouveau-commit`) et votre `HEAD`.\n\nSi vous voulez garder la version du code d'une des branches, vous pouvez utiliser `--ours` ou `--theirs` :\n\n```sh\n(main*)$ git checkout --ours README.md\n```\n\n- Quand vous *fusionnez*, utilisez `--ours` pour garder les modifications de la branche locale, ou `--theirs` pour garder les modifications de l'autre branche.\n- Quand vous *rebasez*, utilisez `--theirs` pour garder les modifications de la branche locale, ou `--ours` pour garder les modifications de l'autre branche. Pour des explications concernant cet échange, consultez [cette note dans la documentation de Git](https://git-scm.com/docs/git-rebase#Documentation/git-rebase.txt---merge).\n\nSi les fusions sont plus complexes, vous pouvez utiliser un éditeur de diff visuel :\n\n```sh\n(main*)$ git mergetool -t opendiff\n```\n\nAprès avoir résolu tous les conflits et testé votre code, faite un `git add` sur les fichiers que vous avez modifiés, puis continuez le rebase avec `git rebase --continue` :\n\n```sh\n(ma-branche)$ git add README.md\n(ma-branche)$ git rebase --continue\n```\n\nSi après avoir résolu tous les conflits, vous finissez avec un arbre identique à ce qu'il était avant le commit, vous devriez faire un `git rebase --skip` à la place.\n\nSi à n'importe quel moment vous voulez arrêter tout le rebase et revenir à l'état initial de votre branche, vous pouvez faire ceci :\n\n```sh\n(ma-branche)$ git rebase --abort\n```\n\n<a name=\"stashing\"></a>\n## Remisage\n\n### Remiser toutes les modifications\n\nPour remiser toutes les modifications dans votre dossier de travail :\n\n```sh\n$ git stash\n```\n\nSi vous voulez également remiser les fichiers non suivis, utilisez l'option `-u` :\n\n```sh\n$ git stash -u\n```\n\n### Remiser des fichiers spécifiques\n\nPour remiser les modifications dans votre dossier de travail uniquement :\n\n```sh\n$ git stash push chemin-du-dossier-de-travail/nomdufichier.ext\n```\n\nPour remiser plusieurs fichiers de votre dossier de travail :\n\n```sh\n$ git stash push chemin-du-dossier-de-travail/nomdufichier1.ext chemin-du-dossier-de-travail/nomdufichier2.ext\n```\n\n<a name=\"stash-msg\"></a>\n### Remiser avec un message\n\n```sh\n$ git stash save <message>\n```\n\n<a name=\"stash-apply-specific\"></a>\n### Appliquer un remisage spécifique de la liste\n\nCommencez par vérifier la liste de vos remisages avec un message en utilisant :\n\n```sh\n$ git stash list\n```\n\nPuis appliquez la commande suivante en choisissant un remisage de la liste :\n\n```sh\n$ git stash apply \"stash@{n}\"\n```\n\nIci, `n` indique la position du remisage dans la pile. Celui le plus haut sera en position 0.\n\n## Rechercher\n\n### Je veux rechercher une chaîne de caractères dans un commit\n\nPour rechercher une certaine chaîne de caractères dans un commit, vous pouvez utiliser la commande suivante :\n\n```sh\n$ git log -S \"chaîne de caractères à rechercher\"\n```\n\nParamètres communs :\n\n* `--source` sert à montrer le nom du ref en se basant sur la ligne de commande avec laquelle chaque commit a été atteint.\n\n* `--all` sert à commencer depuis chaque branche.\n\n* `--reverse` retourne les résultats dans l'ordre inverse, c'est à dire que la commande affichera le premier commit qui a fait la modification.\n\n<a name=\"find-by-committer\"></a>\n### Je veux rechercher par auteur·trice/validateur·trice\n\nPour rechercher des commits par auteur·trice/validateur·trice, vous pouvez utiliser :\n\n```sh\n$ git log --author=<nom ou email>\n$ git log --committer=<nom ou email>\n```\n\nGardez en tête que l'auteur·trice et la personne qui a créé le commit ne sont pas les mêmes personnes. L'option `--author` correspond à la personne qui a écrit le code, et, d'un autre côté, l'option `--committer`, correspond à la personne qui a commité le code au nom de l'autreur·trice.\n\n### Je veux lister les commits ayant des fichiers spécifiques\n\nPour trouver tous les commits contenant un fichier spécifique, vous pouvez utiliser :\n\n```sh\n$ git log -- <chemin du fichier>\n```\n\nEn général, vous préciseriez un chemin exact, mais vous pouvez aussi utiliser des wildcards dans le chemin et le nom du fichier :\n\n```sh\n$ git log -- **/*.js\n```\n\nEn utilisant des wildcards, il est utile de préciser `--name-status` pour voir la liste des fichiers commités :\n\n```sh\n$ git log --name-status -- **/*.js\n```\n\n### Trouver un tag où un commit est référencé\n\nPour trouver tous les tags contenant un commit en particulier :\n\n```sh\n$ git tag --contains <idducommit>\n```\n\n## Sous-modules\n\n<a name=\"clone-submodules\"></a>\n### Cloner tous les sous-modules\n\n```sh\n$ git clone --recursive git://github.com/foo/bar.git\n```\n\nSi ces derniers ont déjà été clonés :\n\n```sh\n$ git submodule update --init --recursive\n```\n\n<a name=\"delete-submodule\"></a>\n### Retirer un sous-module\n\nCréer un sous-module est assez trivial, mais le supprimer l'est moins. Les commandes dont vous avez besoin sont :\n\n```sh\n$ git submodule deinit nomdusubmodule\n$ git rm nomdusubmodule\n$ git rm --cached nomdusubmodule\n$ rm -rf .git/modules/nomdusubmodule\n```\n\n## Objets divers\n\n### Récupérer un fichier supprimé\n\nTrouvez le commit le plus récent où le fichier existait encore :\n\n```sh\n$ git rev-list -n 1 HEAD -- nomdufichier\n```\n\nPuis faites un `checkout` sur ce fichier :\n\n```\ngit checkout idducommitquiasupprimé^ -- nomdufichier\n```\n\n### Supprimer un tag\n\n```sh\n$ git tag -d <nom_du_tag>\n$ git push <remote> :refs/tags/<nom_du_tag>\n```\n\n<a name=\"recover-tag\"></a>\n### Récupérer un tag supprimé\n\nSi vous voulez récupérer un tag qui a déjà été supprimé, vous pouvez le faire en suivant ces étapes :\nTout d'abord, vous devez retrouver le tag inaccessible en question :\n\n```sh\n$ git fsck --unreachable | grep tag\n```\n\nNotez le hash du tag dans un coin. Puis, restaurez le tag supprimé avec la commande suivante, qui utilise [`git update-ref`](https://git-scm.com/docs/git-update-ref) :\n\n```sh\n$ git update-ref refs/tags/<nom_du_tag> <hash>\n```\n\nVotre tag devrait maintenant être restauré.\n\n### Patch supprimé\n\nSi quelqu'un vous a envoyé une Pull Request sur GitHub, mais a par la suite supprimé son fork originel, vous ne serez pas en mesure de cloner son dépôt ou d'utiliser `git am` étant donné que les URLs de [.diff, .patch](https://github.com/blog/967-github-secrets) sont devenues indisponibles. Mais vous pouvez vous déplacer sur la PR en elle-même en utilisant les [les refs spéciaux de GitHub](https://gist.github.com/piscisaureus/3342247). Pour récupérer le contenu de PR#1 vers une nouvelle branche intitulée pr_1 :\n\n```sh\n$ git fetch origin refs/pull/1/head:pr_1\nFrom github.com:foo/bar\n * [new ref]         refs/pull/1/head -> pr_1\n```\n\n### Exporter un dépôt comme fichier Zip\n\n```sh\n$ git archive --format zip --output /full/path/to/zipfile.zip main\n```\n### Pousser une branche et un tag qui ont le même nom\n\nSi un tag sur le dépôt distant a le même nom qu'une branche, vous aurez le message d'erreur suivant en essayant de pousser cette branche avec la commande standard `$ git push <remote> <branche>` :\n\n```sh\n$ git push origin <branch>\nerror: dst refspec same matches more than one.\nerror: failed to push some refs to '<git server>'\n```\n\nRéparez cela en spécifiant que vous voulez pousser la référence de HEAD :\n\n```sh\n$ git push origin refs/heads/<nom-de-la-branche>\n```\n\nSi vous voulez pousser un tag sur un dépôt distant qui a le même nom qu'une branche, vous pouvez utiliser une commande similaire :\n\n```sh\n$ git push origin refs/tags/<nom-du-tag>\n```\n\n## Suivre des fichiers\n\n<a name=\"change-file-name-capitalization-without-changing-contents\"></a>\n### Je veux changer la capitalisation du nom d'un fichier, sans changer son contenu\n\n```sh\n(main)$ git mv --force monFichier MonFichier\n```\n\n### Je veux écraser des fichiers locaux en faisant un git pull\n\n```sh\n(main)$ git fetch --all\n(main)$ git reset --hard origin/main\n```\n\n<a name=\"remove-from-git\"></a>\n### Je veux retirer un fichier de Git mais garder le fichier\n\n```sh\n(main)$ git rm --cached log.txt\n```\n\n### Je veux rétablir un fichier à une version spécifique\n\nSupposons que le hash du commit que vous voulez est `c5f567` :\n\n```sh\n(main)$ git checkout c5f567 -- file1/to/restore file2/to/restore\n```\n\nSi vous voulez rétablir les changements effectués un commit avant `c5f567`, passez le hash du commit comme étant `c5f567~1` :\n\n```sh\n(main)$ git checkout c5f567~1 -- file1/to/restore file2/to/restore\n```\n\n### Je veux lister les changements d'un fichier spécifique entre deux commits ou branches\n\nSupposons que vous voulez comparer le dernier commit avec le fichier du commit `c5f567` :\n\n```sh\n$ git diff HEAD:path_to_file/file c5f567:path_to_file/file\n# ou\n$ git diff HEAD c5f567 -- path_to_file/file\n```\n\nIl en est de même pour les branches :\n\n```sh\n$ git diff main:path_to_file/file staging:path_to_file/file\n# ou\n$ git diff main staging -- path_to_file/file\n```\n\n### Je veux que Git ignore les changements d'un fichier spécifique\n\nCela marche très bien pour le modèles de configurations ou d'autres fichier qui nécessitent d'ajouter des identifiants qui ne devraient pas être commités :\n\n```sh\n$ git update-index --assume-unchanged file-to-ignore\n```\n\nNotez que cela n'enlève *pas* le fichier du suivi - il est seulement ignoré localement. Pour annuler cela et dire à Git de suivre les modifications à nouveau, cette commande supprime le fait d'ignorer :\n\n```sh\n$ git update-index --no-assume-unchanged fichier-à-ne-plus-ignorer\n```\n\n## Paramétrage\n\n### Je veux ajouter des alias pour certaines commandes Git\n\nSur macOS et Linux, votre fichier de configuration Git est stocké dans `~/.gitconfig`. J'ai ajouté des exemples d'alias que j'utilise comme raccourcis (et certaines de mes fautes de frappes) dans la section `[alias]` comme ci-dessous :\n\n```vim\n[alias]\n    a = add\n    amend = commit --amend\n    c = commit\n    ca = commit --amend\n    ci = commit -a\n    co = checkout\n    d = diff\n    dc = diff --changed\n    ds = diff --staged\n    extend = commit --amend -C HEAD\n    f = fetch\n    loll = log --graph --decorate --pretty=oneline --abbrev-commit\n    m = merge\n    one = log --pretty=oneline\n    outstanding = rebase -i @{u}\n    reword = commit --amend --only\n    s = status\n    unpushed = log @{u}\n    wc = whatchanged\n    wip = rebase -i @{u}\n    zap = fetch -p\n```\n\n### Je veux ajouter un répertoire vide à mon dépôt\n\nVous ne pouvez pas ! Git ne supporte pas cela, mais il y a une astuce. Vous pouvez créer un fichier `.gitignore` dans le dossier avec le contenu suivant :\n\n```\n # Ignorer tout dans ce dossier\n *\n # Sauf ce fichier\n !.gitignore\n```\n\nUne autre convention commune est de créer un fichier vide dans le dossier, intitulé `.gitkeep` :\n\n```sh\n$ mkdir mondossier\n$ touch mondossier/.gitkeep\n```\n\nVous pouvez aussi juste appeler le fichier `.keep`, dans ce cas la commande ci-dessus serait `touch mydir/.keep`.\n\n### Je veux mettre en cache un nom d'utilisateur et mot de passe pour un dépôt\n\nIl se peut que vous ayez un dépôt qui nécessite une authentification. Dans ce cas, vous pouvez mettre en cache un nom d'utilisateur et un mot de passe afin que vous n'ayez pas à les rentrer à chaque push / pull. Cette commande peut faire cela pour vous :\n\n```sh\n$ git config --global credential.helper cache\n# Configure Git pour utiliser le cache mémoire des identifiants\n```\n\n```sh\n$ git config --global credential.helper 'cache --timeout=3600'\n# Configurer le cache pour expirer après une heure (le paramètre est en secondes)\n```\n\n### Je veux que Git ignore les changements de permissions et de filemode\n\n```sh\n$ git config core.fileMode false\n```\n\nSi vous voulez configurer cela comme étant le comportement par défaut pour les utilisateurs connectés, utilisez :\n\n```sh\n$ git config --global core.fileMode false\n```\n\n### Je veux définir un utilisateur global\n\nPour configurer des informations d'utilisateur à travers tous les dépôts locaux, et pour configurer un nom qui est identifiable en relisant l'historique :\n\n```sh\n$ git config --global user.name “[prénom nom]”\n```\n\nPour configurer une adresse email qui sera associée à chaque ligne de l'historique :\n\n```sh\ngit config --global user.email “[adresse-email-valide]”\n```\n\n## Je n'ai aucune idée de ce que j'ai mal fait\n\nDonc, vous êtes fichu - vous avez `reset` quelque chose, ou vous avez fusionné la mauvaise branche, ou vous avez poussé de force et maintenant vous ne pouvez plus trouver vos commits. Vous savez qu'à un moment donné, tout allait bien, et vous voulez revenir à un état dans lequel vous étiez avant.\n\nC'est là qu'intervient `git reflog`. `reflog` garde trace de tous les changements du bout de la branche, même si ce dernier n'est pas référencé par une branche ou un tag. Fondamentalement, chaque fois que le HEAD change, une nouvelle entrée est ajoutée au reflog. Cela marche seulement pour les dépôts locaux, malheureusement, et ne trace que les mouvements (pas les changements d'un fichier qui n'ont été enregistrés nulle part, par exemple).\n\n```sh\n(main)$ git reflog\n0a2e358 HEAD@{0}: reset: moving to HEAD~2\n0254ea7 HEAD@{1}: checkout: moving from 2.2 to main\nc10f740 HEAD@{2}: checkout: moving from main to 2.2\n```\n\nLe `reflog` ci-dessus indique un déplacement depuis main vers la branche 2.2 et l'inverse. À partir de là, il y a un hard `reset` vers un commit plus vieux. La dernière activité est représentée en haut et intitulée `HEAD@{0}`.\n\nSi il s'avère que vous êtes accidentellement revenu en arrière, le reflog contiendra le commit sur lequel pointait main (0254ea7) avant que vous ne supprimiez 2 commits par accident.\n\n```sh\n$ git reset --hard 0254ea7\n```\n\nEn utilisant `git reset`, il est ensuite possible de changer main vers le commit vers lequel il pointait. Cela vous donne de la sûreté dans le cas où l'historique a été changé par accident.\n\n(copié et édité depuis [Source](https://www.atlassian.com/git/tutorials/rewriting-history/git-reflog)).\n\n# Autres Ressources\n\n## Livres\n\n* [Learn Enough Git to Be Dangerous](https://www.learnenough.com/git-tutorial) - Un livre de Michael Hartl couvrant les bases de Git\n* [Pro Git](https://git-scm.com/book/en/v2) - L'excellent livre de Scott Chacon et Ben Straub à propos de Git\n* [Git Internals](https://github.com/pluralsight/git-internals-pdf) - L'autre excellent livre de Scott Chacon à propos de Git\n\n## Tutoriels\n\n* [19 Git Tips For Everyday Use](https://www.alexkras.com/19-git-tips-for-everyday-use) - Une liste de commandes Git utiles qui prennent une ligne.\n* [Atlassian's Git tutorial](https://www.atlassian.com/git/tutorials) Comprendre Git avec des tutos à partir du niveau débutant jusqu'au plus avancé.\n* [Learn Git branching](https://learngitbranching.js.org/) Un tutoriel interfactif à base de branch/merge/rebase\n* [Getting solid at Git rebase vs. merge](https://medium.com/@porteneuve/getting-solid-at-git-rebase-vs-merge-4fa1a48c53aa)\n* [Git Commands and Best Practices Cheat Sheet](https://zeroturnaround.com/rebellabs/git-commands-and-best-practices-cheat-sheet) - Un aide-mémoire Git dans un article de blog avec plus d'explications\n* [Git from the inside out](https://codewords.recurse.com/issues/two/git-from-the-inside-out) - Un tutoriel qui plonge dans le fonctionnement interne de Git\n* [git-workflow](https://github.com/asmeurer/git-workflow) - Le tuto d'[Aaron Meurer](https://github.com/asmeurer) à propos de l'utilisation de Git pour contribuer aux dépôts open source\n* [GitHub as a workflow](https://hugogiraudel.com/2015/08/13/github-as-a-workflow/) - Un point de vue intéressant sur l'utilisation de Github en tant que workflow, particulièrement avec des demandes de fusion vides.\n* [Githug](https://github.com/Gazler/githug) - Un jeu pour apprendre les workflows Git les plus communs\n\n## Scripts et Outils\n\n* [firstaidgit.io](http://firstaidgit.io/) Un sélection recherchable des questions Git les plus souvent posées\n* [git-extra-commands](https://github.com/unixorn/git-extra-commands) - Une collection de scripts Git supplémentaires très utiles\n* [git-extras](https://github.com/tj/git-extras) - utilitaires GIT -- résumé de dépôts, repl, population de changelogs, pourcentage de commits par auteur·trice et plus\n* [git-fire](https://github.com/qw3rtman/git-fire) - git-fire est un plugin Git qui vient en aide en cas d'urgence en ajoutant tous les fichier actuels, les commitant, et les poussant vers une nouvelle branche (afin d'éviter les conflits).\n* [git-tips](https://github.com/git-tips/tips) - Des petites astuces Git\n* [git-town](https://github.com/Originate/git-town) - Un support de flux de travail Git générique et de haut-niveau ! http://www.git-town.com\n\n## Clients graphiques\n* [GitKraken](https://www.gitkraken.com/) - Le client Git de luxe pour Windows, Mac & Linux\n* [git-cola](https://git-cola.github.io/) - Un autre client Git pour Windows et macOS\n* [GitUp](https://github.com/git-up/GitUp) - Un client graphique récent qui a une manière dogmatique de gérer les complications de Git\n* [gitx-dev](https://rowanj.github.io/gitx/) - un autre client Git graphique pour macOS\n* [Sourcetree](https://www.sourcetreeapp.com/) - La simplicité alliée à la puissance dans une belle interface gratuite. Pour Windows et Mac\n* [Tower](https://www.git-tower.com/) - Un client graphique pour macOS (payant)\n* [tig](https://jonas.github.io/tig/) - terminal text-mode interface for Git\n* [Magit](https://magit.vc/) - Une interface pour Git implémentée en tant que paquet Emacs.\n* [GitExtensions](https://github.com/gitextensions/gitextensions) - Une extension du shell, un plugin Visual Studio 2010-2015 et un outil de repo Git.\n* [Fork](https://git-fork.com/) - Un client Git rapide et amical pour Mac (beta)\n* [gmaster](https://gmaster.io/) - Un client Git pour Windows qui permet les fusions à 3 branches, l'analyse de refactorisation, un diff et merge sémantique (beta)\n* [gitk](https://git-scm.com/docs/gitk) - Un client Git pour Linux qui permet d'avoir une vue simplifiée de l'état d'un repo.\n* [SublimeMerge](https://www.sublimemerge.com/) - Un client ultra rapide et extensible qui donne la possibilité de faire des fusions à 3 branches, de la recherche avancée et de la colorisation syntaxique, en développement actif.\n"
  },
  {
    "path": "README_ja.md",
    "content": "# Git フライトルール\n\n🌍\n*[English](README.md) ∙ [Español](README_es.md)  ∙  [Русский](README_ru.md) ∙ [繁體中文](README_zh-TW.md) ∙ [简体中文](README_zh-CN.md) ∙ [한국어](README_kr.md)  ∙  [Tiếng Việt](README_vi.md) ∙ [Français](README_fr.md) ∙ [日本語](README_ja.md)*\n\n#### フライトルールとは？\n\n宇宙飛行士（ここでは、Git を使う開発者）が問題に対処するためのガイドです。\n\n> *フライトルール*は、苦心して得た知識体系を、何か起きたときの手順の一つ一つとその理由を記したマニュアルにまとめたものです。基本的に、シナリオごとに標準的な対処法が事細かに説明されています。[...]\n\n> マーキュリー計画のチームが知見を集め始めた 1960 年代から、NASA は私たちの失敗や災難とその解決策を収集してきました。知見の大全は今や、エンジンの不調からハッチハンドルの故障やコンピュータの不具合に至る問題とその対処法に関する、数千ものリストになりました。\n\n&mdash; Chris Hadfield, *An Astronaut's Guide to Life*.\n\n#### この文書で使う記法について\n\n文書の全ての例で、明確さのため、現在のブランチとステージされた編集の有無を表示するようカスタマイズされた Bash プロンプトを使います。\n括弧内にブランチ名を書き、ブランチ名の横の `*` はステージされた編集があることを示します。\n\n全てのコマンドは Git バージョン 2.13.0 から動くはずです。\nGit のバージョンアップについては [Git のウェブサイト](https://www.git-scm.com/) を参照してください。\n\n[![Join the chat at https://gitter.im/k88hudson/git-flight-rules](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/k88hudson/git-flight-rules?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n\n<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**目次**\n\n  - [リポジトリ](#%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA)\n    - [ローカルリポジトリを初期設定したい](#%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E3%82%92%E5%88%9D%E6%9C%9F%E8%A8%AD%E5%AE%9A%E3%81%97%E3%81%9F%E3%81%84)\n    - [リモートリポジトリをクローンしたい](#%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%88%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E3%82%92%E3%82%AF%E3%83%AD%E3%83%BC%E3%83%B3%E3%81%97%E3%81%9F%E3%81%84)\n    - [間違ったリモートリポジトリを設定してしまった](#%E9%96%93%E9%81%95%E3%81%A3%E3%81%9F%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%88%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E3%82%92%E8%A8%AD%E5%AE%9A%E3%81%97%E3%81%A6%E3%81%97%E3%81%BE%E3%81%A3%E3%81%9F)\n    - [他の人のリポジトリにコードを書き加えたい](#%E4%BB%96%E3%81%AE%E4%BA%BA%E3%81%AE%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E3%81%AB%E3%82%B3%E3%83%BC%E3%83%89%E3%82%92%E6%9B%B8%E3%81%8D%E5%8A%A0%E3%81%88%E3%81%9F%E3%81%84)\n      - [プルリクエストでコードを提案するには](#%E3%83%97%E3%83%AB%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%81%A7%E3%82%B3%E3%83%BC%E3%83%89%E3%82%92%E6%8F%90%E6%A1%88%E3%81%99%E3%82%8B%E3%81%AB%E3%81%AF)\n      - [フォークしたリポジトリを、元のリポジトリの最新版に合わせて更新したい](#%E3%83%95%E3%82%A9%E3%83%BC%E3%82%AF%E3%81%97%E3%81%9F%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E3%82%92%E5%85%83%E3%81%AE%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E3%81%AE%E6%9C%80%E6%96%B0%E7%89%88%E3%81%AB%E5%90%88%E3%82%8F%E3%81%9B%E3%81%A6%E6%9B%B4%E6%96%B0%E3%81%97%E3%81%9F%E3%81%84)\n  - [コミットの編集](#%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88%E3%81%AE%E7%B7%A8%E9%9B%86)\n    - [何をコミットしたかわからなくなった](#%E4%BD%95%E3%82%92%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88%E3%81%97%E3%81%9F%E3%81%8B%E3%82%8F%E3%81%8B%E3%82%89%E3%81%AA%E3%81%8F%E3%81%AA%E3%81%A3%E3%81%9F)\n    - [コミットメッセージに間違った内容を書いてしまった](#%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E3%81%AB%E9%96%93%E9%81%95%E3%81%A3%E3%81%9F%E5%86%85%E5%AE%B9%E3%82%92%E6%9B%B8%E3%81%84%E3%81%A6%E3%81%97%E3%81%BE%E3%81%A3%E3%81%9F)\n    - [間違った名前・メールアドレスでコミットしてしまった](#%E9%96%93%E9%81%95%E3%81%A3%E3%81%9F%E5%90%8D%E5%89%8D%E3%83%A1%E3%83%BC%E3%83%AB%E3%82%A2%E3%83%89%E3%83%AC%E3%82%B9%E3%81%A7%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88%E3%81%97%E3%81%A6%E3%81%97%E3%81%BE%E3%81%A3%E3%81%9F)\n    - [直前のコミットからファイルを削除したい](#%E7%9B%B4%E5%89%8D%E3%81%AE%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88%E3%81%8B%E3%82%89%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E5%89%8A%E9%99%A4%E3%81%97%E3%81%9F%E3%81%84)\n    - [直前のコミットを削除したい](#%E7%9B%B4%E5%89%8D%E3%81%AE%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88%E3%82%92%E5%89%8A%E9%99%A4%E3%81%97%E3%81%9F%E3%81%84)\n    - [特定のコミットを削除したい](#%E7%89%B9%E5%AE%9A%E3%81%AE%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88%E3%82%92%E5%89%8A%E9%99%A4%E3%81%97%E3%81%9F%E3%81%84)\n    - [修正したコミットをリモートにプッシュしようとしたら、エラーメッセージが出た](#%E4%BF%AE%E6%AD%A3%E3%81%97%E3%81%9F%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88%E3%82%92%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%88%E3%81%AB%E3%83%97%E3%83%83%E3%82%B7%E3%83%A5%E3%81%97%E3%82%88%E3%81%86%E3%81%A8%E3%81%97%E3%81%9F%E3%82%89%E3%82%A8%E3%83%A9%E3%83%BC%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E3%81%8C%E5%87%BA%E3%81%9F)\n    - [間違えて hard reset してしまい、元に戻したい](#%E9%96%93%E9%81%95%E3%81%88%E3%81%A6-hard-reset-%E3%81%97%E3%81%A6%E3%81%97%E3%81%BE%E3%81%84%E5%85%83%E3%81%AB%E6%88%BB%E3%81%97%E3%81%9F%E3%81%84)\n    - [間違えてマージをコミットしてプッシュしてしまった](#%E9%96%93%E9%81%95%E3%81%88%E3%81%A6%E3%83%9E%E3%83%BC%E3%82%B8%E3%82%92%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88%E3%81%97%E3%81%A6%E3%83%97%E3%83%83%E3%82%B7%E3%83%A5%E3%81%97%E3%81%A6%E3%81%97%E3%81%BE%E3%81%A3%E3%81%9F)\n    - [間違えて機密情報を含むファイルをコミットしプッシュしてしまった](#%E9%96%93%E9%81%95%E3%81%88%E3%81%A6%E6%A9%9F%E5%AF%86%E6%83%85%E5%A0%B1%E3%82%92%E5%90%AB%E3%82%80%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88%E3%81%97%E3%83%97%E3%83%83%E3%82%B7%E3%83%A5%E3%81%97%E3%81%A6%E3%81%97%E3%81%BE%E3%81%A3%E3%81%9F)\n    - [大容量のファイルに関する履歴を完全に削除したい](#%E5%A4%A7%E5%AE%B9%E9%87%8F%E3%81%AE%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AB%E9%96%A2%E3%81%99%E3%82%8B%E5%B1%A5%E6%AD%B4%E3%82%92%E5%AE%8C%E5%85%A8%E3%81%AB%E5%89%8A%E9%99%A4%E3%81%97%E3%81%9F%E3%81%84)\n      - [おすすめの方法：サードパーティ製の bfg を使う](#%E3%81%8A%E3%81%99%E3%81%99%E3%82%81%E3%81%AE%E6%96%B9%E6%B3%95%E3%82%B5%E3%83%BC%E3%83%89%E3%83%91%E3%83%BC%E3%83%86%E3%82%A3%E8%A3%BD%E3%81%AE-bfg-%E3%82%92%E4%BD%BF%E3%81%86)\n      - [ビルトインの方法：git-filter-branch を使う](#%E3%83%93%E3%83%AB%E3%83%88%E3%82%A4%E3%83%B3%E3%81%AE%E6%96%B9%E6%B3%95git-filter-branch-%E3%82%92%E4%BD%BF%E3%81%86)\n      - [最後のステップ: 変更した履歴をプッシュする](#%E6%9C%80%E5%BE%8C%E3%81%AE%E3%82%B9%E3%83%86%E3%83%83%E3%83%97-%E5%A4%89%E6%9B%B4%E3%81%97%E3%81%9F%E5%B1%A5%E6%AD%B4%E3%82%92%E3%83%97%E3%83%83%E3%82%B7%E3%83%A5%E3%81%99%E3%82%8B)\n    - [直近でないコミットの内容を編集したい](#%E7%9B%B4%E8%BF%91%E3%81%A7%E3%81%AA%E3%81%84%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88%E3%81%AE%E5%86%85%E5%AE%B9%E3%82%92%E7%B7%A8%E9%9B%86%E3%81%97%E3%81%9F%E3%81%84)\n  - [ステージ](#%E3%82%B9%E3%83%86%E3%83%BC%E3%82%B8)\n    - [バージョン管理されているファイルを全部ステージしたい](#%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E7%AE%A1%E7%90%86%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%82%8B%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E5%85%A8%E9%83%A8%E3%82%B9%E3%83%86%E3%83%BC%E3%82%B8%E3%81%97%E3%81%9F%E3%81%84)\n      - [バージョン管理されているファイルの一部をステージするには](#%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E7%AE%A1%E7%90%86%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%82%8B%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E4%B8%80%E9%83%A8%E3%82%92%E3%82%B9%E3%83%86%E3%83%BC%E3%82%B8%E3%81%99%E3%82%8B%E3%81%AB%E3%81%AF)\n    - [ステージされた編集を直前のコミットに追加したい](#%E3%82%B9%E3%83%86%E3%83%BC%E3%82%B8%E3%81%95%E3%82%8C%E3%81%9F%E7%B7%A8%E9%9B%86%E3%82%92%E7%9B%B4%E5%89%8D%E3%81%AE%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88%E3%81%AB%E8%BF%BD%E5%8A%A0%E3%81%97%E3%81%9F%E3%81%84)\n    - [新しいファイルの全部ではなく一部をステージしたい](#%E6%96%B0%E3%81%97%E3%81%84%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E5%85%A8%E9%83%A8%E3%81%A7%E3%81%AF%E3%81%AA%E3%81%8F%E4%B8%80%E9%83%A8%E3%82%92%E3%82%B9%E3%83%86%E3%83%BC%E3%82%B8%E3%81%97%E3%81%9F%E3%81%84)\n    - [一つのファイルに加えた編集を二つの異なるコミットに追加したい](#%E4%B8%80%E3%81%A4%E3%81%AE%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AB%E5%8A%A0%E3%81%88%E3%81%9F%E7%B7%A8%E9%9B%86%E3%82%92%E4%BA%8C%E3%81%A4%E3%81%AE%E7%95%B0%E3%81%AA%E3%82%8B%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88%E3%81%AB%E8%BF%BD%E5%8A%A0%E3%81%97%E3%81%9F%E3%81%84)\n    - [ステージした編集が多すぎるので、いくつかのコミットに分割したい](#%E3%82%B9%E3%83%86%E3%83%BC%E3%82%B8%E3%81%97%E3%81%9F%E7%B7%A8%E9%9B%86%E3%81%8C%E5%A4%9A%E3%81%99%E3%81%8E%E3%82%8B%E3%81%AE%E3%81%A7%E3%81%84%E3%81%8F%E3%81%A4%E3%81%8B%E3%81%AE%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88%E3%81%AB%E5%88%86%E5%89%B2%E3%81%97%E3%81%9F%E3%81%84)\n    - [ステージされていない編集をステージし、ステージされた編集のステージを取り消したい](#%E3%82%B9%E3%83%86%E3%83%BC%E3%82%B8%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%81%AA%E3%81%84%E7%B7%A8%E9%9B%86%E3%82%92%E3%82%B9%E3%83%86%E3%83%BC%E3%82%B8%E3%81%97%E3%82%B9%E3%83%86%E3%83%BC%E3%82%B8%E3%81%95%E3%82%8C%E3%81%9F%E7%B7%A8%E9%9B%86%E3%81%AE%E3%82%B9%E3%83%86%E3%83%BC%E3%82%B8%E3%82%92%E5%8F%96%E3%82%8A%E6%B6%88%E3%81%97%E3%81%9F%E3%81%84)\n  - [ステージされていない編集](#%E3%82%B9%E3%83%86%E3%83%BC%E3%82%B8%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%81%AA%E3%81%84%E7%B7%A8%E9%9B%86)\n    - [ステージされていない編集を新しいブランチに移したい](#%E3%82%B9%E3%83%86%E3%83%BC%E3%82%B8%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%81%AA%E3%81%84%E7%B7%A8%E9%9B%86%E3%82%92%E6%96%B0%E3%81%97%E3%81%84%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%81%AB%E7%A7%BB%E3%81%97%E3%81%9F%E3%81%84)\n    - [ステージされていない編集を別の既存のブランチに移したい](#%E3%82%B9%E3%83%86%E3%83%BC%E3%82%B8%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%81%AA%E3%81%84%E7%B7%A8%E9%9B%86%E3%82%92%E5%88%A5%E3%81%AE%E6%97%A2%E5%AD%98%E3%81%AE%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%81%AB%E7%A7%BB%E3%81%97%E3%81%9F%E3%81%84)\n    - [コミットされていないローカルの編集を破棄したい](#%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%81%AA%E3%81%84%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E3%81%AE%E7%B7%A8%E9%9B%86%E3%82%92%E7%A0%B4%E6%A3%84%E3%81%97%E3%81%9F%E3%81%84)\n    - [ステージされていない特定の編集を破棄したい](#%E3%82%B9%E3%83%86%E3%83%BC%E3%82%B8%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%81%AA%E3%81%84%E7%89%B9%E5%AE%9A%E3%81%AE%E7%B7%A8%E9%9B%86%E3%82%92%E7%A0%B4%E6%A3%84%E3%81%97%E3%81%9F%E3%81%84)\n    - [ステージされていない特定のファイルを破棄したい](#%E3%82%B9%E3%83%86%E3%83%BC%E3%82%B8%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%81%AA%E3%81%84%E7%89%B9%E5%AE%9A%E3%81%AE%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E7%A0%B4%E6%A3%84%E3%81%97%E3%81%9F%E3%81%84)\n    - [ステージされていないローカルな編集だけを破棄したい](#%E3%82%B9%E3%83%86%E3%83%BC%E3%82%B8%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%81%AA%E3%81%84%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E3%81%AA%E7%B7%A8%E9%9B%86%E3%81%A0%E3%81%91%E3%82%92%E7%A0%B4%E6%A3%84%E3%81%97%E3%81%9F%E3%81%84)\n    - [バージョン管理されていないファイルを全て破棄したい](#%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E7%AE%A1%E7%90%86%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%81%AA%E3%81%84%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E5%85%A8%E3%81%A6%E7%A0%B4%E6%A3%84%E3%81%97%E3%81%9F%E3%81%84)\n    - [特定のステージされたファイルのステージを取り消したい](#%E7%89%B9%E5%AE%9A%E3%81%AE%E3%82%B9%E3%83%86%E3%83%BC%E3%82%B8%E3%81%95%E3%82%8C%E3%81%9F%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E3%82%B9%E3%83%86%E3%83%BC%E3%82%B8%E3%82%92%E5%8F%96%E3%82%8A%E6%B6%88%E3%81%97%E3%81%9F%E3%81%84)\n  - [ブランチ](#%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81)\n    - [全ブランチの一覧を表示したい](#%E5%85%A8%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%81%AE%E4%B8%80%E8%A6%A7%E3%82%92%E8%A1%A8%E7%A4%BA%E3%81%97%E3%81%9F%E3%81%84)\n    - [コミットからブランチを作成する](#%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88%E3%81%8B%E3%82%89%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B)\n    - [間違ったブランチから、あるいは間違ったブランチにプルしてしまった](#%E9%96%93%E9%81%95%E3%81%A3%E3%81%9F%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%81%8B%E3%82%89%E3%81%82%E3%82%8B%E3%81%84%E3%81%AF%E9%96%93%E9%81%95%E3%81%A3%E3%81%9F%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%81%AB%E3%83%97%E3%83%AB%E3%81%97%E3%81%A6%E3%81%97%E3%81%BE%E3%81%A3%E3%81%9F)\n    - [ローカルのコミットを破棄して、ブランチをサーバ上と同じ状態にしたい](#%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E3%81%AE%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88%E3%82%92%E7%A0%B4%E6%A3%84%E3%81%97%E3%81%A6%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%82%92%E3%82%B5%E3%83%BC%E3%83%90%E4%B8%8A%E3%81%A8%E5%90%8C%E3%81%98%E7%8A%B6%E6%85%8B%E3%81%AB%E3%81%97%E3%81%9F%E3%81%84)\n    - [新しいブランチではなくマスターブランチにコミットしてしまった](#%E6%96%B0%E3%81%97%E3%81%84%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%81%A7%E3%81%AF%E3%81%AA%E3%81%8F%E3%83%9E%E3%82%B9%E3%82%BF%E3%83%BC%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%81%AB%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88%E3%81%97%E3%81%A6%E3%81%97%E3%81%BE%E3%81%A3%E3%81%9F)\n    - [ファイル全てをリファレンス的な場所に保存しておきたい](#%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E5%85%A8%E3%81%A6%E3%82%92%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9%E7%9A%84%E3%81%AA%E5%A0%B4%E6%89%80%E3%81%AB%E4%BF%9D%E5%AD%98%E3%81%97%E3%81%A6%E3%81%8A%E3%81%8D%E3%81%9F%E3%81%84)\n    - [別々のブランチにするべき複数のコミットを一つのブランチにしてしまった](#%E5%88%A5%E3%80%85%E3%81%AE%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%81%AB%E3%81%99%E3%82%8B%E3%81%B9%E3%81%8D%E8%A4%87%E6%95%B0%E3%81%AE%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88%E3%82%92%E4%B8%80%E3%81%A4%E3%81%AE%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%81%AB%E3%81%97%E3%81%A6%E3%81%97%E3%81%BE%E3%81%A3%E3%81%9F)\n    - [upstream で削除されたローカルブランチを削除したい](#upstream-%E3%81%A7%E5%89%8A%E9%99%A4%E3%81%95%E3%82%8C%E3%81%9F%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%82%92%E5%89%8A%E9%99%A4%E3%81%97%E3%81%9F%E3%81%84)\n    - [間違ってブランチを削除してしまった](#%E9%96%93%E9%81%95%E3%81%A3%E3%81%A6%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%82%92%E5%89%8A%E9%99%A4%E3%81%97%E3%81%A6%E3%81%97%E3%81%BE%E3%81%A3%E3%81%9F)\n    - [ブランチを削除したい](#%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%82%92%E5%89%8A%E9%99%A4%E3%81%97%E3%81%9F%E3%81%84)\n    - [複数のブランチを削除したい](#%E8%A4%87%E6%95%B0%E3%81%AE%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%82%92%E5%89%8A%E9%99%A4%E3%81%97%E3%81%9F%E3%81%84)\n    - [ブランチの名前を変更したい](#%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%81%AE%E5%90%8D%E5%89%8D%E3%82%92%E5%A4%89%E6%9B%B4%E3%81%97%E3%81%9F%E3%81%84)\n    - [他の人が作業しているリモートブランチにチェックアウトしたい](#%E4%BB%96%E3%81%AE%E4%BA%BA%E3%81%8C%E4%BD%9C%E6%A5%AD%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%88%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%81%AB%E3%83%81%E3%82%A7%E3%83%83%E3%82%AF%E3%82%A2%E3%82%A6%E3%83%88%E3%81%97%E3%81%9F%E3%81%84)\n    - [現在のローカルブランチをもとに新しいリモートブランチを作成したい](#%E7%8F%BE%E5%9C%A8%E3%81%AE%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%82%92%E3%82%82%E3%81%A8%E3%81%AB%E6%96%B0%E3%81%97%E3%81%84%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%88%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%82%92%E4%BD%9C%E6%88%90%E3%81%97%E3%81%9F%E3%81%84)\n    - [リモートブランチをローカルブランチの upstream に設定したい](#%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%88%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%82%92%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%81%AE-upstream-%E3%81%AB%E8%A8%AD%E5%AE%9A%E3%81%97%E3%81%9F%E3%81%84)\n    - [自分の HEAD をデフォルトのリモートブランチを追跡するよう設定したい](#%E8%87%AA%E5%88%86%E3%81%AE-head-%E3%82%92%E3%83%87%E3%83%95%E3%82%A9%E3%83%AB%E3%83%88%E3%81%AE%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%88%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%82%92%E8%BF%BD%E8%B7%A1%E3%81%99%E3%82%8B%E3%82%88%E3%81%86%E8%A8%AD%E5%AE%9A%E3%81%97%E3%81%9F%E3%81%84)\n    - [間違ったブランチを編集してしまった](#%E9%96%93%E9%81%95%E3%81%A3%E3%81%9F%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%82%92%E7%B7%A8%E9%9B%86%E3%81%97%E3%81%A6%E3%81%97%E3%81%BE%E3%81%A3%E3%81%9F)\n  - [リベースとマージ](#%E3%83%AA%E3%83%99%E3%83%BC%E3%82%B9%E3%81%A8%E3%83%9E%E3%83%BC%E3%82%B8)\n    - [リベースやマージを取り消したい](#%E3%83%AA%E3%83%99%E3%83%BC%E3%82%B9%E3%82%84%E3%83%9E%E3%83%BC%E3%82%B8%E3%82%92%E5%8F%96%E3%82%8A%E6%B6%88%E3%81%97%E3%81%9F%E3%81%84)\n    - [リベースしたが、強制プッシュはしたくない](#%E3%83%AA%E3%83%99%E3%83%BC%E3%82%B9%E3%81%97%E3%81%9F%E3%81%8C%E5%BC%B7%E5%88%B6%E3%83%97%E3%83%83%E3%82%B7%E3%83%A5%E3%81%AF%E3%81%97%E3%81%9F%E3%81%8F%E3%81%AA%E3%81%84)\n    - [コミットを統合したい](#%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88%E3%82%92%E7%B5%B1%E5%90%88%E3%81%97%E3%81%9F%E3%81%84)\n      - [安全なマージの方法](#%E5%AE%89%E5%85%A8%E3%81%AA%E3%83%9E%E3%83%BC%E3%82%B8%E3%81%AE%E6%96%B9%E6%B3%95)\n      - [ブランチを一つのコミットにまとめたい場合](#%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%82%92%E4%B8%80%E3%81%A4%E3%81%AE%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88%E3%81%AB%E3%81%BE%E3%81%A8%E3%82%81%E3%81%9F%E3%81%84%E5%A0%B4%E5%90%88)\n      - [プッシュされていないコミットのみを統合したい場合](#%E3%83%97%E3%83%83%E3%82%B7%E3%83%A5%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%81%AA%E3%81%84%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88%E3%81%AE%E3%81%BF%E3%82%92%E7%B5%B1%E5%90%88%E3%81%97%E3%81%9F%E3%81%84%E5%A0%B4%E5%90%88)\n      - [マージを中止したい](#%E3%83%9E%E3%83%BC%E3%82%B8%E3%82%92%E4%B8%AD%E6%AD%A2%E3%81%97%E3%81%9F%E3%81%84)\n    - [ブランチの親コミットを更新したい](#%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%81%AE%E8%A6%AA%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88%E3%82%92%E6%9B%B4%E6%96%B0%E3%81%97%E3%81%9F%E3%81%84)\n    - [ブランチの全コミットがマージされているか確認する](#%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%81%AE%E5%85%A8%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88%E3%81%8C%E3%83%9E%E3%83%BC%E3%82%B8%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%82%8B%E3%81%8B%E7%A2%BA%E8%AA%8D%E3%81%99%E3%82%8B)\n    - [対話的リベースで起こりうる問題](#%E5%AF%BE%E8%A9%B1%E7%9A%84%E3%83%AA%E3%83%99%E3%83%BC%E3%82%B9%E3%81%A7%E8%B5%B7%E3%81%93%E3%82%8A%E3%81%86%E3%82%8B%E5%95%8F%E9%A1%8C)\n      - [リベース編集画面に 'noop' と表示される](#%E3%83%AA%E3%83%99%E3%83%BC%E3%82%B9%E7%B7%A8%E9%9B%86%E7%94%BB%E9%9D%A2%E3%81%AB-noop-%E3%81%A8%E8%A1%A8%E7%A4%BA%E3%81%95%E3%82%8C%E3%82%8B)\n      - [コンフリクトがあった](#%E3%82%B3%E3%83%B3%E3%83%95%E3%83%AA%E3%82%AF%E3%83%88%E3%81%8C%E3%81%82%E3%81%A3%E3%81%9F)\n  - [スタッシュ](#%E3%82%B9%E3%82%BF%E3%83%83%E3%82%B7%E3%83%A5)\n    - [全ての編集をスタッシュしたい](#%E5%85%A8%E3%81%A6%E3%81%AE%E7%B7%A8%E9%9B%86%E3%82%92%E3%82%B9%E3%82%BF%E3%83%83%E3%82%B7%E3%83%A5%E3%81%97%E3%81%9F%E3%81%84)\n    - [特定のファイルをスタッシュしたい](#%E7%89%B9%E5%AE%9A%E3%81%AE%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E3%82%B9%E3%82%BF%E3%83%83%E3%82%B7%E3%83%A5%E3%81%97%E3%81%9F%E3%81%84)\n    - [メッセージをつけてスタッシュしたい](#%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E3%82%92%E3%81%A4%E3%81%91%E3%81%A6%E3%82%B9%E3%82%BF%E3%83%83%E3%82%B7%E3%83%A5%E3%81%97%E3%81%9F%E3%81%84)\n    - [一覧から特定のスタッシュを選んで適用したい](#%E4%B8%80%E8%A6%A7%E3%81%8B%E3%82%89%E7%89%B9%E5%AE%9A%E3%81%AE%E3%82%B9%E3%82%BF%E3%83%83%E3%82%B7%E3%83%A5%E3%82%92%E9%81%B8%E3%82%93%E3%81%A7%E9%81%A9%E7%94%A8%E3%81%97%E3%81%9F%E3%81%84)\n    - [ステージされていない編集をそのままにしつつ、スタッシュしたい](#%E3%82%B9%E3%83%86%E3%83%BC%E3%82%B8%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%81%AA%E3%81%84%E7%B7%A8%E9%9B%86%E3%82%92%E3%81%9D%E3%81%AE%E3%81%BE%E3%81%BE%E3%81%AB%E3%81%97%E3%81%A4%E3%81%A4%E3%82%B9%E3%82%BF%E3%83%83%E3%82%B7%E3%83%A5%E3%81%97%E3%81%9F%E3%81%84)\n  - [検索](#%E6%A4%9C%E7%B4%A2)\n    - [全コミットから文字列を検索したい](#%E5%85%A8%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88%E3%81%8B%E3%82%89%E6%96%87%E5%AD%97%E5%88%97%E3%82%92%E6%A4%9C%E7%B4%A2%E3%81%97%E3%81%9F%E3%81%84)\n    - [author または committer から検索する](#author-%E3%81%BE%E3%81%9F%E3%81%AF-committer-%E3%81%8B%E3%82%89%E6%A4%9C%E7%B4%A2%E3%81%99%E3%82%8B)\n    - [特定のファイルを含むコミットの一覧を表示したい](#%E7%89%B9%E5%AE%9A%E3%81%AE%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E5%90%AB%E3%82%80%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88%E3%81%AE%E4%B8%80%E8%A6%A7%E3%82%92%E8%A1%A8%E7%A4%BA%E3%81%97%E3%81%9F%E3%81%84)\n    - [特定の関数に関するコミット履歴を見たい](#%E7%89%B9%E5%AE%9A%E3%81%AE%E9%96%A2%E6%95%B0%E3%81%AB%E9%96%A2%E3%81%99%E3%82%8B%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88%E5%B1%A5%E6%AD%B4%E3%82%92%E8%A6%8B%E3%81%9F%E3%81%84)\n    - [コミットが参照されているタグを検索したい](#%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88%E3%81%8C%E5%8F%82%E7%85%A7%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%82%8B%E3%82%BF%E3%82%B0%E3%82%92%E6%A4%9C%E7%B4%A2%E3%81%97%E3%81%9F%E3%81%84)\n  - [サブモジュール](#%E3%82%B5%E3%83%96%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB)\n    - [全てのサブモジュールをクローンする](#%E5%85%A8%E3%81%A6%E3%81%AE%E3%82%B5%E3%83%96%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB%E3%82%92%E3%82%AF%E3%83%AD%E3%83%BC%E3%83%B3%E3%81%99%E3%82%8B)\n    - [サブモジュールを削除する](#%E3%82%B5%E3%83%96%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB%E3%82%92%E5%89%8A%E9%99%A4%E3%81%99%E3%82%8B)\n  - [その他色々](#%E3%81%9D%E3%81%AE%E4%BB%96%E8%89%B2%E3%80%85)\n    - [あるブランチから別のブランチにフォルダをコピーしたい](#%E3%81%82%E3%82%8B%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%81%8B%E3%82%89%E5%88%A5%E3%81%AE%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%81%AB%E3%83%95%E3%82%A9%E3%83%AB%E3%83%80%E3%82%92%E3%82%B3%E3%83%94%E3%83%BC%E3%81%97%E3%81%9F%E3%81%84)\n    - [削除されたファイルを復元したい](#%E5%89%8A%E9%99%A4%E3%81%95%E3%82%8C%E3%81%9F%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E5%BE%A9%E5%85%83%E3%81%97%E3%81%9F%E3%81%84)\n    - [タグを削除したい](#%E3%82%BF%E3%82%B0%E3%82%92%E5%89%8A%E9%99%A4%E3%81%97%E3%81%9F%E3%81%84)\n    - [削除されたタグを復元したい](#%E5%89%8A%E9%99%A4%E3%81%95%E3%82%8C%E3%81%9F%E3%82%BF%E3%82%B0%E3%82%92%E5%BE%A9%E5%85%83%E3%81%97%E3%81%9F%E3%81%84)\n    - [削除されたパッチを取得したい](#%E5%89%8A%E9%99%A4%E3%81%95%E3%82%8C%E3%81%9F%E3%83%91%E3%83%83%E3%83%81%E3%82%92%E5%8F%96%E5%BE%97%E3%81%97%E3%81%9F%E3%81%84)\n    - [リポジトリを zip ファイルとしてエクスポートしたい](#%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E3%82%92-zip-%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%A8%E3%81%97%E3%81%A6%E3%82%A8%E3%82%AF%E3%82%B9%E3%83%9D%E3%83%BC%E3%83%88%E3%81%97%E3%81%9F%E3%81%84)\n    - [同じ名前のブランチとタグをプッシュしたい](#%E5%90%8C%E3%81%98%E5%90%8D%E5%89%8D%E3%81%AE%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%81%A8%E3%82%BF%E3%82%B0%E3%82%92%E3%83%97%E3%83%83%E3%82%B7%E3%83%A5%E3%81%97%E3%81%9F%E3%81%84)\n  - [ファイルの追跡](#%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E8%BF%BD%E8%B7%A1)\n    - [ファイルの内容は変えずに、ファイル名の大文字・小文字を変更したい](#%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E5%86%85%E5%AE%B9%E3%81%AF%E5%A4%89%E3%81%88%E3%81%9A%E3%81%AB%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E5%90%8D%E3%81%AE%E5%A4%A7%E6%96%87%E5%AD%97%E3%83%BB%E5%B0%8F%E6%96%87%E5%AD%97%E3%82%92%E5%A4%89%E6%9B%B4%E3%81%97%E3%81%9F%E3%81%84)\n    - [git pull してローカルのファイルを上書きしたい](#git-pull-%E3%81%97%E3%81%A6%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E3%81%AE%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E4%B8%8A%E6%9B%B8%E3%81%8D%E3%81%97%E3%81%9F%E3%81%84)\n    - [ファイルを残しつつ Git から削除したい](#%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E6%AE%8B%E3%81%97%E3%81%A4%E3%81%A4-git-%E3%81%8B%E3%82%89%E5%89%8A%E9%99%A4%E3%81%97%E3%81%9F%E3%81%84)\n    - [ファイルを特定の版まで差し戻したい](#%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E7%89%B9%E5%AE%9A%E3%81%AE%E7%89%88%E3%81%BE%E3%81%A7%E5%B7%AE%E3%81%97%E6%88%BB%E3%81%97%E3%81%9F%E3%81%84)\n    - [特定のファイルのコミット間・ブランチ間の差分を表示したい](#%E7%89%B9%E5%AE%9A%E3%81%AE%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88%E9%96%93%E3%83%BB%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E9%96%93%E3%81%AE%E5%B7%AE%E5%88%86%E3%82%92%E8%A1%A8%E7%A4%BA%E3%81%97%E3%81%9F%E3%81%84)\n    - [特定のファイルの変更を無視したい](#%E7%89%B9%E5%AE%9A%E3%81%AE%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E5%A4%89%E6%9B%B4%E3%82%92%E7%84%A1%E8%A6%96%E3%81%97%E3%81%9F%E3%81%84)\n  - [Git によるデバッグ](#git-%E3%81%AB%E3%82%88%E3%82%8B%E3%83%87%E3%83%90%E3%83%83%E3%82%B0)\n  - [設定](#%E8%A8%AD%E5%AE%9A)\n    - [Git コマンドにエイリアスを設定したい](#git-%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%AB%E3%82%A8%E3%82%A4%E3%83%AA%E3%82%A2%E3%82%B9%E3%82%92%E8%A8%AD%E5%AE%9A%E3%81%97%E3%81%9F%E3%81%84)\n    - [空のディレクトリをリポジトリに加えたい](#%E7%A9%BA%E3%81%AE%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA%E3%82%92%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E3%81%AB%E5%8A%A0%E3%81%88%E3%81%9F%E3%81%84)\n    - [リポジトリへのユーザ名とパスワードをキャッシュしたい](#%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E3%81%B8%E3%81%AE%E3%83%A6%E3%83%BC%E3%82%B6%E5%90%8D%E3%81%A8%E3%83%91%E3%82%B9%E3%83%AF%E3%83%BC%E3%83%89%E3%82%92%E3%82%AD%E3%83%A3%E3%83%83%E3%82%B7%E3%83%A5%E3%81%97%E3%81%9F%E3%81%84)\n    - [パーミッションとファイルモードの変更を Git が無視するようにしたい](#%E3%83%91%E3%83%BC%E3%83%9F%E3%83%83%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%A8%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%83%A2%E3%83%BC%E3%83%89%E3%81%AE%E5%A4%89%E6%9B%B4%E3%82%92-git-%E3%81%8C%E7%84%A1%E8%A6%96%E3%81%99%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB%E3%81%97%E3%81%9F%E3%81%84)\n    - [グローバルユーザを設定したい](#%E3%82%B0%E3%83%AD%E3%83%BC%E3%83%90%E3%83%AB%E3%83%A6%E3%83%BC%E3%82%B6%E3%82%92%E8%A8%AD%E5%AE%9A%E3%81%97%E3%81%9F%E3%81%84)\n  - [何を間違ったかわからないとき](#%E4%BD%95%E3%82%92%E9%96%93%E9%81%95%E3%81%A3%E3%81%9F%E3%81%8B%E3%82%8F%E3%81%8B%E3%82%89%E3%81%AA%E3%81%84%E3%81%A8%E3%81%8D)\n  - [Git ショートカット](#git-%E3%82%B7%E3%83%A7%E3%83%BC%E3%83%88%E3%82%AB%E3%83%83%E3%83%88)\n    - [Git Bash](#git-bash)\n    - [Windows の PowerShell](#windows-%E3%81%AE-powershell)\n- [文献](#%E6%96%87%E7%8C%AE)\n  - [本](#%E6%9C%AC)\n  - [チュートリアル](#%E3%83%81%E3%83%A5%E3%83%BC%E3%83%88%E3%83%AA%E3%82%A2%E3%83%AB)\n  - [スクリプトとツール](#%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E3%81%A8%E3%83%84%E3%83%BC%E3%83%AB)\n  - [GUI クライアント](#gui-%E3%82%AF%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%B3%E3%83%88)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n## リポジトリ\n\n### ローカルリポジトリを初期設定したい\n\n既存のディレクトリを Git リポジトリとして初期設定するには、次を実行します。\n\n```sh\n(my-folder) $ git init\n```\n\n### リモートリポジトリをクローンしたい\n\nリモートリポジトリをクローン（コピー）したいときは、リポジトリの URL をコピーし、次を実行します。\n\n```sh\n$ git clone [url]\n```\n\nすると、リモートリポジトリと同名のフォルダにリポジトリの内容が保存されます。\nリモートリポジトリのあるサーバに接続できる必要があります。大抵の場合インターネット接続があれば大丈夫です。\n\nリモートリポジトリと異なる名前のフォルダにクローンしたいときは、次のようにします。\n\n```sh\n$ git clone [url] name-of-new-folder\n```\n\n### 間違ったリモートリポジトリを設定してしまった\n\n問題はいくつかの場合に分けられます。\n\n間違ったリポジトリをクローンしてしまったときは、`git clone` で作ったディレクトリを削除して、正しいリポジトリをクローンし直せばよいです。\n\n間違ったリポジトリを既存のローカルリポジトリの origin に設定してしまったときは、次のように origin の URL を変更しましょう。\n\n```sh\n$ git remote set-url origin [url of the actual repo]\n```\n\nほかの問題は[この StackOverflow トピック](https://stackoverflow.com/questions/2432764/how-to-change-the-uri-url-for-a-remote-git-repository#2432799)を参照してください。\n\n### 他の人のリポジトリにコードを書き加えたい\n\nGit では、アクセス権がないかぎり他の人のリポジトリに書き込むことはできません。\nGitHub は Git リポジトリのホスティングサービスであって Git 自体とは異なるものですが、GitHub でもやはり同様です。\nしかし、パッチでコードを提案することができます。\nGitHub ならフォークとプルリクエストの機能がこれにあたります。\n\nまずはフォークについて説明しましょう。\nフォークはリポジトリのコピーです。\nGit 自体の機能ではないものの、GitHub, BitBucket, GitLab やその他のホスティングサービスにはこの機能があり、各サービスの UI を通して実行できます。\n\n#### プルリクエストでコードを提案するには\n\nリポジトリをフォークしたら、ローカルマシンにクローンして編集しましょう。\nちょっとした編集なら GitHub 上でもできるでしょうが、この文書は GitHub フライトルールではないので、ローカルで編集する方法を説明します。\n\n```sh\n# ssh を使う場合\n$ git clone git@github.com:k88hudson/git-flight-rules.git\n\n# https を使う場合\n$ git clone https://github.com/k88hudson/git-flight-rules.git\n```\n\nできたディレクトリに `cd` で移動し、`git remote` を実行してください。\nリモートのリストが表示されるはずです。\nただ、おそらく表示されるのは `k88hudson/git-flight-rules` を参照する `origin` だけなので、自分がフォークして作った方のリモートも用意する必要があります。\n\nGit では、自分自身のリポジトリのリモートは `origin`、フォークした元のリポジトリには `upstream` と名付けるのが一般的です。\nこれにならって、まず、リモート `origin` の名前を `upstream` に変更しましょう。\n\n```sh\n$ git remote rename origin upstream\n```\n\n実は `git remote set-url` でも同じことができますが、時間と手間が余計にかかります。\n\n次に、自分のプロジェクトを参照する新しいリモートを作成します。\n\n```sh\n$ git remote add origin git@github.com:YourName/git-flight-rules.git\n```\n\nこの時点でリモートは二つです。\n\n- `origin` は自分のリポジトリを参照しています。\n- `upstream` は元のリポジトリを参照しています。\n\n`origin` は読み取り・書き込みの両方ができ、`upstream` は読み取り専用です。\n\n編集が済んだら、編集を（通常はブランチ内から）リモート `origin` にプッシュしましょう。\nブランチ内にいる場合、次のように `--set-upstream` を使うと、次回から同じブランチからプッシュする際にリモートを指定せずに済みます。\n\n```sh\n$ (feature/my-feature) git push --set-upstream origin feature/my-feature\n```\n\nGit で CLI からプルリクエストを送る方法はありません（[hub](http://github.com/github/hub) のようなツールを使えば別ですが）。\nプルリクエストを送りたいときは、GitHub（あるいは他のホスティングサービス）上でプルリクエストを作成してください。\n元のリポジトリとフォークしたリポジトリの紐付けはホスティングサービスが自動的にしてくれます。\n\nプルリクエストの後、コードレビューのフィードバックに対応するのを忘れないようにしましょう。\n\n#### フォークしたリポジトリを、元のリポジトリの最新版に合わせて更新したい\n\nそのうち `upstream` リポジトリが更新され、自分の `origin` にプルしたくなるかもしれません。\n自分だけでなく他の人も共同作業していることを忘れないようにしてください。\n自分のフィーチャーブランチにいて、これを元のリポジトリに合わせて更新したい場合を想定します。\n\n元のプロジェクトを参照するリモートは設定してありますか？　まだなら今やってしまいましょう。\n通常はリモートの名前に `upstream` を使います。\n\n```sh\n$ (main) git remote add upstream <link-to-original-repository>\n# $ (main) git remote add upstream git@github.com:k88hudson/git-flight-rules.git\n```\n\nこれで `upstream` から最新版を取得できるようになりました。\n\n```sh\n$ (main) git fetch upstream\n$ (main) git merge upstream/main\n\n# コマンド一つでもできる\n$ (main) git pull upstream main\n```\n\n## コミットの編集\n\n<a name=\"diff-last\"></a>\n### 何をコミットしたかわからなくなった\n\n何も考えず `git commit -a` で編集をコミットしてしまい、その内容がわからないとします。\n現在の HEAD の最新のコミット内容は次のように表示できます。\n\n```sh\n(main)$ git show\n```\n\nもしくは次の通りです。\n\n```sh\n$ git log -n1 -p\n```\n\n特定のコミットの時点のファイルの中身を見たいときは次のようにします（`<commitid>` は見たいコミット）。\n\n```sh\n$ git show <commitid>:filename\n```\n\n<a name=\"wrong-thing-in-commit-message\"></a>\n### コミットメッセージに間違った内容を書いてしまった\n\nコミットメッセージに間違った内容を書いてしまったとします。\nコミットがまだプッシュされていない場合は、次のようにして編集は変えずにコミットメッセージを編集できます。\n\n```sh\n$ git commit --amend --only\n```\n\nデフォルトのテキストエディタが開き、コミットメッセージを編集できます。\n次のようにして、一つのコマンドでいっぺんにやることもできます。\n\n```sh\n$ git commit --amend --only -m 'xxxxxxx'\n```\n\nすでにコミットをプッシュしてしまった場合、コミットを修正して強制プッシュすることはできますが、おすすめしません。\n\n<a name=\"commit-wrong-author\"></a>\n### 間違った名前・メールアドレスでコミットしてしまった\n\nコミットが一つだけなら、次のように修正します。\n\n```sh\n$ git commit --amend --no-edit --author \"New Authorname <authoremail@mydomain.com>\"\n```\n\nあるいは、名前とメールアドレスを `git config --global author.(name|email)` で正しく設定してから、次を実行します。\n\n```sh\n$ git commit --amend --reset-author --no-edit\n```\n\n履歴すべてについて変更したい場合は、`git filter-branch` の man ページを参照してください。\n\n### 直前のコミットからファイルを削除したい\n\n直前のコミットから特定のファイルに関する編集を削除するには次のようにします。\n\n```sh\n$ git checkout HEAD^ myfile\n$ git add myfile\n$ git commit --amend --no-edit\n```\n\n直前のコミットで新たに追加したファイルを（Git のみから）削除したいときは次の通りです。\n\n```sh\n$ git rm --cached myfile\n$ git commit --amend --no-edit\n```\n\nこのコマンドは、不要なファイルをパッチにコミットしてしまい、強制プッシュでリモートのパッチを更新したいときに特に便利です。\nオプション `--no-edit` は既存のコミットメッセージを変更しないようにするためのものです。\n\n<a name=\"delete-pushed-commit\"></a>\n### 直前のコミットを削除したい\n\nすでにプッシュしたコミットを削除するには次のようにします。\nただし、編集履歴が不可逆的に変更され、リポジトリから変更内容をプルしてしまった他の人の編集履歴は滅茶苦茶になります。\n要するに、よくわからない場合は絶対にしないでください。\n\n```sh\n$ git reset HEAD^ --hard\n$ git push --force-with-lease [remote] [branch]\n```\n\nまだコミットをプッシュしていない場合は、次のようにして（ステージされた編集はそのままで）直前のコミットをする前の状態に Git をリセットできます。\n\n```\n(my-branch)$ git reset --soft HEAD^\n```\n\nこれはプッシュしていない場合にのみ有効な方法です。\nプッシュしてしまった場合、本当に安全な方法は `git revert SHAofBadCommit` だけです。\nこのコマンドは、直前のコミットを相殺するようなコミットを新たに作成します。\nプッシュしたブランチがリベースについて安全である場合（つまり、他の開発者がプルすることを想定していない場合）は、`git push --force-with-lease` を使っても大丈夫です。\n<!--For more, see [the above section](#deleteremove-last-pushed-commit).-->\n\n<a name=\"delete-any-commit\"></a>\n### 特定のコミットを削除したい\n\n上と同様に、やむを得ない場合以外絶対に行わないでください。\n\n```sh\n$ git rebase --onto SHA1_OF_BAD_COMMIT^ SHA1_OF_BAD_COMMIT\n$ git push --force-with-lease [remote] [branch]\n```\n\nあるいは、[対話的 rebase](#interactive-rebase) で削除したいコミットに対応する行を選択して削除します。\n\n<a name=\"force-push\"></a>\n### 修正したコミットをリモートにプッシュしようとしたら、エラーメッセージが出た\n\n```sh\nTo https://github.com/yourusername/repo.git\n! [rejected]        mybranch -> mybranch (non-fast-forward)\nerror: failed to push some refs to 'https://github.com/tanay1337/webmaker.org.git'\nhint: Updates were rejected because the tip of your current branch is behind\nhint: its remote counterpart. Integrate the remote changes (e.g.\nhint: 'git pull ...') before pushing again.\nhint: See the 'Note about fast-forwards' in 'git push --help' for details.\n```\n\namend による修正は、rebase と同様に（後述）、**古いコミットを新たなコミットで置き換えます**。\nそれゆえ、修正前のコミットをすでにリモートにプッシュしてしまった場合は、強制プッシュ (`--force-with-lease`) しなければいけません。\n強制プッシュには細心の注意が必要です。\n*必ず*ブランチを指定するように！\n\n```sh\n(my-branch)$ git push origin mybranch --force-with-lease\n```\n\n一般論として、**強制プッシュは避けましょう**。\n修正したコミットを強制プッシュするよりは、新たなコミットを作ってプッシュするのがベストです。\n強制プッシュは、対象のブランチやその子ブランチで作業した他の開発者のソース履歴にコンフリクトをきたします。\n誰かが同じブランチで作業していて、強制プッシュがその人の編集を上書きしてしまう場合は、`--force-with-lease` も失敗します。\n\n他の誰も同じブランチで作業していないことが*絶対に*確実な場合、あるいはブランチの一部を*無条件で*更新したい場合は `--force` (`-f`) で行うことができますが、これは原則として避けるべきです。\n\n<a name=\"undo-git-reset-hard\"></a>\n### 間違えて hard reset してしまい、元に戻したい\n\n間違えて `git reset --hard` をしてしまっても、大抵はコミットを復元できます。\nGit は数日間のログを全て残してくれているからです。\n\n注意：これは作業がバックアップされている場合、つまりコミットないしスタッシュされている場合に限ります。\n`git reset --hard` はコミットされていない変更を*削除*してしまうので、注意して使ってください。\n（安全なのは `git reset --keep` を使うことです。）\n\n```sh\n(main)$ git reflog\n```\n\n過去のコミットとリセットに対応するコミットが表示されるので、復元したいコミットの SHA を選んでリセットします。\n\n```sh\n(main)$ git reset --hard SHA1234\n```\n\nこれで大丈夫です。\n\n<a name=\"undo-a-commit-merge\"></a>\n### 間違えてマージをコミットしてプッシュしてしまった\n\nマージの準備ができていないフィーチャーブランチをメインのブランチにマージしてしまったときは、マージを取り消すことができます。\nただし注意すべき点は、マージコミットには複数（通常は二つ）の親があることです。\n\n次のコマンドを実行します。\n\n```sh\n(feature-branch)$ git revert -m 1 <commit>\n```\n\nここでオプション `-m 1` は差し戻す先の親として親 1（マージした先のブランチ）を指定します。\n\n注意：親の番号はコミット ID とは異なります。\nマージコミットの行は `Merge: 8e2ce2d 86ac2e7` のようになっています。\n親番号はこのコミットの親を指定する 1 から始まる番号で、最初の番号は 1 番、次は 2 番、のように振られます。\n\n<a name=\"undo-sensitive-commit-push\"></a>\n### 間違えて機密情報を含むファイルをコミットしプッシュしてしまった\n\n機密情報やプライベートな情報（パスワードやキー等）を含むデータを誤ってプッシュしてしまった場合、コミットを修正できます。\nただし、ひとたびデータをコミットしてプッシュしてしまったら、その内容は盗み取られるおそれがあることに留意してください。\n下の手順で公開リポジトリやローカルからデータを削除できますが、他の誰かがすでにプルしたデータを削除することは**不可能です**。\nパスワードをコミットしてしまった場合は**直ちに変更してください**。\nキーをコミットしてしまった場合は**直ちに再生成しましょう**。\n誰かがすでに機密情報をプルしてしまった可能性がある限り、プッシュしたコミットを修正するだけでは不十分です。\n\nファイルを編集して機密情報を削除したあと、次を実行します。\n\n```sh\n(feature-branch)$ git add edited_file\n(feature-branch)$ git commit --amend --no-edit\n(feature-branch)$ git push --force-with-lease origin [branch]\n```\n\nファイルごと削除したいがローカルには残しておきたい場合、次を実行します。\n\n```sh\n(feature-branch)$ git rm --cached sensitive_file\necho sensitive_file >> .gitignore\n(feature-branch)$ git add .gitignore\n(feature-branch)$ git commit --amend --no-edit\n(feature-branch)$ git push --force-with-lease origin [branch]\n```\n\nあるいは、機密情報をローカルの環境変数に保存しておきましょう。\n\nファイルごと削除した上でローカルからも削除したい場合は、次を実行します。\n\n```sh\n(feature-branch)$ git rm sensitive_file\n(feature-branch)$ git commit --amend --no-edit\n(feature-branch)$ git push --force-with-lease origin [branch]\n```\n\nすでに他のコミットをしてしまった場合（つまり、機密情報のコミットが直前のコミットよりも前である場合）は、リベースする必要があります。\n\n<a name=\"remove-large-file-in-repo-history\"></a>\n### 大容量のファイルに関する履歴を完全に削除したい\n\n削除したいファイルが機密情報である場合は[機密情報を削除する方法](#undo-sensitive-commit-push)を参照してください。\n\nコミットで大容量のファイルや不要なファイルを削除しても、`.git` フォルダの Git 履歴には残るので、`git clone` したときに余計なファイルまでダウンロードしてしまうことになります。\n\nここで説明する手順には強制プッシュを必要とし、リポジトリ履歴を大きく変更してしまいます。\n誰かがリモートで共同作業している場合は、全員のローカルの編集履歴がプッシュされていることを確認しておいてください。\n\n履歴を書き換えるには二つの方法があります。\nビルトインの `git-filter-branch` と [`bfg-repo-cleaner`](https://rtyley.github.io/bfg-repo-cleaner/) です。\n`bfg` はエレガントで性能がよい一方、サードパーティ製のソフトをダウンロードしなければならず、Java も必要です。\nここでは両方を説明します。\n最後のステップでは強制プッシュをしますが、リポジトリの履歴の大部分を永久に変更するため、通常の強制プッシュよりもなお特別な配慮が必要になります。\n\n#### おすすめの方法：サードパーティ製の bfg を使う\n\nbfg-repo-cleaner を使うには Java が必要です。\n[ここ](https://rtyley.github.io/bfg-repo-cleaner/)から bfg の jar ファイルをダウンロードしてください。\n下の例では `bfg.jar` を使いますが、ダウンロードしたものには `bfg-1.13.0.jar` のようにバージョン番号がついているかもしれません。\n\n特定のファイルを削除する場合は次のようにします。\n\n```sh\n(main)$ git rm path/to/filetoremove\n(main)$ git commit -m \"Commit removing filetoremove\"\n(main)$ java -jar ~/Downloads/bfg.jar --delete-files filetoremove\n```\n\nなお、bfg を使うときは、ファイルがサブディレクトリにあってもそのままのファイル名を入力することに注意してください。\n\nパターンからファイルを削除することもできます。例えば次の通りです。\n\n```sh\n(main)$ git rm *.jpg\n(main)$ git commit -m \"Commit removing *.jpg\"\n(main)$ java -jar ~/Downloads/bfg.jar --delete-files *.jpg\n```\n\nbfg は最新のコミットにあるファイルには影響しません。\n例えば、リポジトリに複数あった大容量の .tga ファイルのうち一部を以前のコミットで削除したとして、bfg を実行しても最新のコミットにあるファイルはそのままです。\n\nなお、コミットでファイル名を変更した場合、例えばもともと `LargeFileFirstName.mp4` だったファイルが後のコミットで `LargeFileSecondName.mp4` に変更されている場合は、`java -jar ~/Downloads/bfg.jar --delete-files LargeFileSecondName.mp4` を実行しても Git の履歴からは削除されません。\n両方のファイル名それぞれについて `--delete-files` を実行するか、パターンマッチで両方削除してください。\n\n#### ビルトインの方法：git-filter-branch を使う\n\n`git-filter-branch` はややこしくて機能も貧弱ですが、`bfg` のインストールや実行ができなくても使えます。\n\n以下では、`filepattern` を名前やパターン（`*.jpg` など）に置き換えてください。\nパターンにマッチしたファイルの履歴が全ての履歴とブランチから削除されます。\n\n```sh\n(main)$ git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch filepattern' --prune-empty --tag-name-filter cat -- --all\n```\n\nここで使っている `--tag-name-filter cat` は煩雑ですが、このように `cat` を使うのが元のタグを新しいコミットにつける最も簡単な方法です。\nまた、`--prune-empty` は現在空のコミットを全て削除します。\n\n#### 最後のステップ: 変更した履歴をプッシュする\n\nファイルを削除したら、リポジトリのものを壊していないか慎重に確認してください。\n何か壊してしまった場合は、リポジトリを再度クローンしてやり直すのが最も簡単です。\n最後のステップとして、必要に応じて Git ガベージコレクションで .git フォルダの容量を最小化してから、強制プッシュします。\n\n```sh\n(main)$ git reflog expire --expire=now --all && git gc --prune=now --aggressive\n(main)$ git push origin --force --tags\n```\n\nリポジトリの履歴を全て書き換えているので、`git push` の量が膨大すぎて `“The remote end hung up unexpectedly”` というエラーが返るかもしれません。\nその場合は Git の post buffer を増やしてみます。\n\n```sh\n(main)$ git config http.postBuffer 524288000\n(main)$ git push --force\n```\n\nうまくいかない場合は、コミットを手作業で小分けにしてプッシュします。\nプッシュが成功するまで、`<number>` を増やしながら次のコマンドを試してください。\n\n```sh\n(main)$ git push -u origin HEAD~<number>:refs/head/main --force\n```\n\nプッシュが成功したら、通常の`git push` が 成功するまで `<number>` を徐々に減らしてください。\n\n<a name=\"change-content-of-commit-not-my-last\"></a>\n### 直近でないコミットの内容を編集したい\n\n複数（たとえば三件）のコミットを行ったあと、文脈的に最初のコミットに属する作業をし忘れたことに気づいたとします。\nこの作業を新たなコミットとして行えばコードベースは綺麗に保てるものの、コミットがアトミックでなくなってしまう（同じ文脈の作業が同じコミットに属さない）ので、この状況は厄介です。\nし忘れた作業が属するべきコミットを編集して作業を取り入れつつ、その後のコミットには手をつけないようにしたいとき、`git rebase` が役に立ちます。\n\n最後から三件目のコミットを編集したいとします。\n\n```sh\n(your-branch)$ git rebase -i HEAD~4\n```\n\n上のコマンドで対話的リベースモードに入り、直近三件のコミットを編集できるようになります。\nテキストエディタが開き、次のような内容が表示されます。\n\n```sh\npick 9e1d264 The third last commit\npick 4b6e19a The second to last commit\npick f4037ec The last commit\n```\n\nこれを次のように編集します。\n\n```sh\nedit 9e1d264 The third last commit\npick 4b6e19a The second to last commit\npick f4037ec The last commit\n```\n\nこれは最後から三件目のコミットを編集しつつ、他の二件はそのままにするよう `rebase` に指示するコマンドです。\nテキストエディタを保存して終了したら、Git がリベースを始めます。指定したコミットで止まり、そのコミットを編集できるようになります。\nこれで最初にコミットしたときにし忘れた作業を適用できます。編集とステージによって適用しましょう。\nその後、次を実行します。\n\n```sh\n(your-branch)$ git commit --amend\n```\n\nこれはコミットメッセージはそのままでコミットを作り直すよう Git に指示するコマンドです。\nこれで面倒な作業は終わりです。\n\n```sh\n(your-branch)$ git rebase --continue\n```\n\nあとは上を実行すれば完了です。\n\n## ステージ\n\n<a name=\"stage-tracked-files-and-leave-untracked-files\"></a>\n### バージョン管理されているファイルを全部ステージしたい\n\n```sh\n$ git add -u\n```\n\n#### バージョン管理されているファイルの一部をステージするには\n\n```sh\n# 拡張子が .txt のファイルをステージする\n$ git add -u *.txt\n\n# src ディレクトリ内の全ファイルをステージする\n$ git add -u src/\n```\n\n<a name=\"add-staged-changes-to-previous-commit\"></a>\n### ステージされた編集を直前のコミットに追加したい\n\n```sh\n(my-branch*)$ git commit --amend\n```\n\nコミットメッセージを変更したくないときは、コミットメッセージを再利用するよう Git に指示します。\n\n```sh\n(my-branch*)$ git commit --amend -C HEAD\n```\n\n<a name=\"commit-partial-new-file\"></a>\n### 新しいファイルの全部ではなく一部をステージしたい\n\n通常、ファイルの一部をステージするには次を実行します。\n\n```sh\n$ git add --patch filename.x\n```\n\n短縮形は `-p` です。これにより対話モードが開きます。\nオプション `s` をつけるとコミットを分割 (split) できます。ただし、新しく作ったファイルの場合このオプションは使えません。\nファイルを新たに追加するには、次を実行します。\n\n```sh\n$ git add -N filename.x\n```\n\nオプション `e` を使うと、どの行を追加するか手動で選択することができます。\nコマンド `git diff --cached` あるいは `git diff --staged` を実行すると、ステージした行がローカルに保存されたものと比較して表示されます。\n\n<a name=\"stage-in-two-commits\"></a>\n### 一つのファイルに加えた編集を二つの異なるコミットに追加したい\n\nコマンド `git add` はファイル全体をコミットに追加します。\nまた、`git add -p` を使うと、どの編集を追加するか対話的に選択できます。\n\n<a name=\"selective-unstage-edits\"></a>\n### ステージした編集が多すぎるので、いくつかのコミットに分割したい\n\nコマンド `git reset -p` を実行すると、パッチモードのリセットダイアログが開きます。\nなお、`git add -p` と似ていますが、\"yes\" がステージを取り消して次のコミットから除去することを意味する点で異なります。\n\n<a name=\"unstaging-edits-and-staging-the-unstaged\"></a>\n### ステージされていない編集をステージし、ステージされた編集のステージを取り消したい\n\n通常は、ステージされたファイルのステージを一旦全部取り消したあと、コミットしたいものをピックするべきです。\nステージされている編集とされていない編集を切り替えたいときは、ステージされた編集を記録しておく仮のコミットを作成し、ステージされていないファイルをステージしてスタッシュします。\nそれから仮のコミットをリセットして、スタッシュを pop します。\n\n```sh\n$ git commit -m \"WIP\"\n$ git add . # バージョン管理されていないファイルも追加される\n$ git stash\n$ git reset HEAD^\n$ git stash pop --index 0\n```\n\n注意 1：ここで `pop` を使うのは、操作を複数回行ってもなるべく結果が変わらないようにするためです。\n\n注意 2：ここで `--index` を指定しないと、ステージされたファイルはステージされていない扱いになります（理由は[このリンク](https://stackoverflow.com/questions/31595873/git-stash-with-staged-files-does-stash-convert-staged-files-to-unstaged?answertab=active#tab-top)を参照してください）。\n\n## ステージされていない編集\n\n<a name=\"move-unstaged-edits-to-new-branch\"></a>\n### ステージされていない編集を新しいブランチに移したい\n\n```sh\n$ git checkout -b my-branch\n```\n\n<a name=\"move-unstaged-edits-to-old-branch\"></a>\n### ステージされていない編集を別の既存のブランチに移したい\n\n```sh\n$ git stash\n$ git checkout my-branch\n$ git stash pop\n```\n\n<a name=\"discard-local-uncommitted-changes\"></a>\n### コミットされていないローカルの編集を破棄したい\n\nステージされている編集とされていない編集の両方を全て破棄したいときは、次のようにします。\n\n```sh\n(my-branch)$ git reset --hard\n# または\n(main)$ git checkout -f\n```\n\n次のコマンドは `git add` でステージした全ファイルのステージを取り消します。\n\n```sh\n$ git reset\n```\n\n次のコマンドはコミットされていないローカルの編集を全て差し戻します（リポジトリのルートで実行する必要があります）。\n\n```sh\n$ git checkout .\n```\n\n特定のファイルやディレクトリについて、コミットされていない編集を差し戻すこともできます。\n\n```sh\n$ git checkout [some_dir|file.txt]\n```\n\nコミットされていない編集を全て差し戻すのには次の方法もあります（コマンドが長いですが、全てのサブディレクトリから実行できます）。\n\n```sh\n$ git reset --hard HEAD\n```\n\n次を実行するとローカルのバージョン管理されていないファイルが全て削除されます。\nつまり、Git で管理されているファイルだけ残ります。\n\n```sh\n$ git clean -fd\n```\n\nGit に無視されるファイルも全て取り除くには `-x` を指定します。\n\n### ステージされていない特定の編集を破棄したい\n\nワークツリーの編集の全部ではなく一部だけを破棄したい場合です。\n\n残したい編集だけを残し、残したくない編集をチェックアウトします。\n\n```sh\n$ git checkout -p\n# 破棄したいコードすべてについて y と答える\n```\n\nもう一つの方法は `stash` を使います。残したい編集をスタッシュし、ワークツリーをリセットして、残したい編集を適用します。\n\n```sh\n$ git stash -p\n# 残したいコードを全て選ぶ\n$ git reset --hard\n$ git stash pop\n```\n\nあるいは、残したくない編集をスタッシュして、スタッシュを破棄してもよいです。\n\n```sh\n$ git stash -p\n# 残したくないコードを全て選ぶ\n$ git stash drop\n```\n\n### ステージされていない特定のファイルを破棄したい\n\nワークツリーの特定のファイル一つを取り除きたいときです。\n\n```sh\n$ git checkout myFile\n```\n\nワークツリー上の複数のファイルを破棄したいときは、破棄したいファイルを列挙します。\n\n```sh\n$ git checkout myFirstFile mySecondFile\n```\n\n### ステージされていないローカルな編集だけを破棄したい\n\nコミットもステージもされていないローカルの編集を全て破棄したいときは、次を実行します。\n\n```sh\n$ git checkout .\n```\n\n<a name=\"discard-all-untracked-files\"></a>\n### バージョン管理されていないファイルを全て破棄したい\n\nバージョン管理されていないファイルを全て破棄したいときは、次を実行します。\n\n```sh\n$ git clean -f\n```\n\n<a name=\"unstage-specific-staged-file\"></a>\n### 特定のステージされたファイルのステージを取り消したい\n\n間違えてステージしたが、コミットはしていないファイルが一つまたは複数ある場合です。\nそのステージを取り消すには次のようにします。\n\n```sh\n$ git reset -- <filename>\n```\n\nファイルのステージが取り消され、バージョン管理されていないものとみなされます。\n\n## ブランチ\n\n### 全ブランチの一覧を表示したい\n\nローカルブランチの一覧を表示\n\n```sh\n$ git branch\n```\n\nリモートブランチの一覧を表示\n\n```sh\n$ git branch -r\n```\n\nローカルとリモート両方のブランチの一覧を表示\n\n```sh\n$ git branch -a\n```\n\n<a name=\"create-branch-from-commit\"></a>\n### コミットからブランチを作成する\n\n```sh\n$ git checkout -b <branch> <SHA1_OF_COMMIT>\n```\n\n<a name=\"pull-wrong-branch\"></a>\n### 間違ったブランチから、あるいは間違ったブランチにプルしてしまった\n\nこれも `git reflog` を使う場面です。\n間違ったプルの前に HEAD が参照していたものを表示します。\n\n```sh\n(main)$ git reflog\nab7555f HEAD@{0}: pull origin wrong-branch: Fast-forward\nc5bc55a HEAD@{1}: checkout: checkout message goes here\n```\n\nブランチを適切なコミットにリセットするだけです。\n\n```sh\n$ git reset --hard c5bc55a\n```\n\nこれで完了です。\n\n<a name=\"discard-local-commits\"></a>\n### ローカルのコミットを破棄して、ブランチをサーバ上と同じ状態にしたい\n\nサーバに編集をプッシュしていないことを確認してください。\n\nコマンド `git status` を実行すると、自分が origin に対して何コミット分作業を進めたのか表示されます。\n\n```sh\n(my-branch)$ git status\n# On branch my-branch\n# Your branch is ahead of 'origin/my-branch' by 2 commits.\n#   (use \"git push\" to publish your local commits)\n#\n```\n\norigin と同じ状態にリセットする（リモートと同じ状態にする）方法の一つは次の通りです。\n\n```sh\n(my-branch)$ git reset --hard origin/my-branch\n```\n\n<a name=\"commit-wrong-branch\"></a>\n### 新しいブランチではなくマスターブランチにコミットしてしまった\n\nマスターブランチにいたまま、新しいブランチを作成してください。\n\n```sh\n(main)$ git branch my-branch\n```\n\nマスターブランチを直前のコミットにリセットします。\n\n```sh\n(main)$ git reset --hard HEAD^\n```\n\nここで `HEAD^` は `HEAD^1` の短縮形で、`HEAD` の第一の親を表します。\n同様に `HEAD^2` は第二の親です（マージには親が二つあります）。\n\nなお、`HEAD^2` は `HEAD~2` と**異なる**ことに注意してください（詳しくは[このリンク](http://www.paulboxley.com/blog/2011/06/git-caret-and-tilde)を参照してください）。\n\nあるいは `HEAD^` を使いたくなければ、マスターブランチを差し戻したい先のコミットハッシュを探し（`git log` を使うとよいです）、そのハッシュにリセットします。\nあとは `git push` すればリモートに反映されるはずです。\n\n例えば、マスターブランチを差し戻したいコミットのハッシュが `a13b85e` なら、次のようにします。\n\n```sh\n(main)$ git reset --hard a13b85e\nHEAD is now at a13b85e\n```\n\n作業に戻るため、新しいブランチにチェックアウトしましょう。\n\n```sh\n(main)$ git checkout my-branch\n```\n\n<a name=\"keep-whole-file\"></a>\n### ファイル全てをリファレンス的な場所に保存しておきたい\n\nワーキングスパイク（メモを参照）にたくさん編集があって、すべてうまく機能しているものとします。\nこの作業内容を保存しておくため、別のブランチにコミットします。\n\n```sh\n(solution)$ git add -A && git commit -m \"Adding all changes from this spike into one big commit.\"\n```\n\nこの内容をブランチ（フィーチャーブランチでも `develop` でも）に適用する際は、ファイル全部を保存しておきたいはずです。\n大きなコミットを小さなコミットに分割します。\n\nいま、次のブランチがあるものとします。\n\n* `solution` ブランチ。スパイクを解消するためのブランチで、`develop` ブランチに対して一コミット分進んでいます。\n* `develop` ブランチ。ここに編集を適用したいとします。\n\nこれは編集をブランチに適用することで可能です。\n\n```sh\n(develop)$ git checkout solution -- file1.txt\n```\n\nこれで `solution` ブランチの内容が `develop` ブランチに適用されます。\n\n```sh\n# On branch develop\n# Your branch is up-to-date with 'origin/develop'.\n# Changes to be committed:\n#  (use \"git reset HEAD <file>...\" to unstage)\n#\n#        modified:   file1.txt\n```\n\nあとは通常通りコミットしてください。\n\nメモ：スパイクは問題を解析したり解決するためのものです。\n解決法は判断にかけられたあと、共同開発者が問題を理解した時点で破棄されます。~ [Wikipedia](https://en.wikipedia.org/wiki/Extreme_programming_practices)\n\n<a name=\"cherry-pick\"></a>\n### 別々のブランチにするべき複数のコミットを一つのブランチにしてしまった\n\nマスターブランチにいるとして、`git log` でコミットが二つ表示されるとします。\n\n```sh\n(main)$ git log\n\ncommit e3851e817c451cc36f2e6f3049db528415e3c114\nAuthor: Alex Lee <alexlee@example.com>\nDate:   Tue Jul 22 15:39:27 2014 -0400\n\n    Bug #21 - Added CSRF protection\n\ncommit 5ea51731d150f7ddc4a365437931cd8be3bf3131\nAuthor: Alex Lee <alexlee@example.com>\nDate:   Tue Jul 22 15:39:12 2014 -0400\n\n    Bug #14 - Fixed spacing on title\n\ncommit a13b85e984171c6e2a1729bb061994525f626d14\nAuthor: Aki Rose <akirose@example.com>\nDate:   Tue Jul 21 01:12:48 2014 -0400\n\n    First commit\n```\n\nそれぞれのバグに対応するコミットハッシュをメモしておきます（#21 は`e3851e8`、#14 は`5ea5173` です）。\n\nまず、次のようにしてマスターブランチをあるべきコミット `a13b85e` までリセットします。\n\n```sh\n(main)$ git reset --hard a13b85e\nHEAD is now at a13b85e\n```\n\nこれで、バグ #21 に対応する新しいブランチを作成できます。\n\n```sh\n(main)$ git checkout -b 21\n(21)$\n```\n\nさて、このブランチにコミットを**チェリーピック**しましょう。\nつまり、head が何であろうとそこに当該コミットだけを適用します。\n\n```sh\n(21)$ git cherry-pick e3851e8\n```\n\nこの時点で、コミットのコンフリクトが発生しているかもしれません。\nコンフリクトを解消する方法は、[対話的 rebase 章上](#interactive-rebase) セクションの [**コンフリクトがあった**](#merge-conflict) を参照してください。\n\n次に、#14 に対応する、マスターに紐づいたブランチを作成しましょう。\n\n```sh\n(21)$ git checkout main\n(main)$ git checkout -b 14\n(14)$\n```\n\n最後に、バグ #14 に対応するコミットをチェリーピックします。\n\n```sh\n(14)$ git cherry-pick 5ea5173\n```\n\n<a name=\"delete-stale-local-branches\"></a>\n### upstream で削除されたローカルブランチを削除したい\n\nGitHub でプルリクエストをマージすると、マージされたブランチを自分のフォークから削除する選択肢が出てきます。\nそのブランチで今後作業するつもりがなければ、もはや使わないブランチで作業環境が散らからないように削除しておくほうが綺麗です。\n\n```sh\n$ git fetch -p upstream\n```\n\nここで `upstream` は取得したい元のリモートを指します。\n\n<a name=\"restore-a-deleted-branch\"></a>\n### 間違ってブランチを削除してしまった\n\nいつもリモートにプッシュしているなら大抵大丈夫です。\nブランチを間違って削除してしまうのはよくあることです。\n\n新しくブランチを作り、ファイルを新規作成したとします。\n\n```sh\n(main)$ git checkout -b my-branch\n(my-branch)$ git branch\n(my-branch)$ touch foo.txt\n(my-branch)$ ls\nREADME.md foo.txt\n```\n\nこれを追加してコミットします。\n\n```sh\n(my-branch)$ git add .\n(my-branch)$ git commit -m 'foo.txt added'\n(my-branch)$ foo.txt added\n 1 files changed, 1 insertions(+)\n create mode 100644 foo.txt\n(my-branch)$ git log\n\ncommit 4e3cd85a670ced7cc17a2b5d8d3d809ac88d5012\nAuthor: siemiatj <siemiatj@example.com>\nDate:   Wed Jul 30 00:34:10 2014 +0200\n\n    foo.txt added\n\ncommit 69204cdf0acbab201619d95ad8295928e7f411d5\nAuthor: Kate Hudson <katehudson@example.com>\nDate:   Tue Jul 29 13:14:46 2014 -0400\n\n    Fixes #6: Force pushing after amending commits\n```\n\nマスターに戻って、「間違って」ブランチを削除してみます。\n\n```sh\n(my-branch)$ git checkout main\nSwitched to branch 'main'\nYour branch is up-to-date with 'origin/main'.\n(main)$ git branch -D my-branch\nDeleted branch my-branch (was 4e3cd85).\n(main)$ echo oh noes, deleted my branch!\noh noes, deleted my branch!\n```\n\nさて、ここで改良されたロガー `reflog` について学びましょう。\nこれはリポジトリの全ての操作履歴を保存しています。\n\n```\n(main)$ git reflog\n69204cd HEAD@{0}: checkout: moving from my-branch to main\n4e3cd85 HEAD@{1}: commit: foo.txt added\n69204cd HEAD@{2}: checkout: moving from main to my-branch\n```\n\nこのように、削除してしまったブランチのコミットが表示されています。\n削除したブランチを復元してみましょう。\n\n```sh\n(main)$ git checkout -b my-branch-help\nSwitched to a new branch 'my-branch-help'\n(my-branch-help)$ git reset --hard 4e3cd85\nHEAD is now at 4e3cd85 foo.txt added\n(my-branch-help)$ ls\nREADME.md foo.txt\n```\n\nやった！　消えたファイルを取り戻しました。\nコマンド `git reflog` は、リベースが滅茶苦茶になってしまったときにも便利です。\n\n### ブランチを削除したい\n\nリモートブランチを削除するには次を実行します。\n\n```sh\n(main)$ git push origin --delete my-branch\n```\n\n次のようにもできます。\n\n```sh\n(main)$ git push origin :my-branch\n```\n\nローカルブランチを削除するには次の通りです。\n\n```sh\n(main)$ git branch -d my-branch\n```\n\n現在のブランチか upstream にマージ**されていない**ブランチを削除するには次のようにします。\n\n```sh\n(main)$ git branch -D my-branch\n```\n\n### 複数のブランチを削除したい\n\n名前が `fix/` で始まるブランチを全て削除したいときは次の通りです。\n\n```sh\n(main)$ git branch | grep 'fix/' | xargs git branch -d\n```\n\n### ブランチの名前を変更したい\n\n現在の（ローカル）ブランチの名前を変更するには次を実行します。\n\n```sh\n(main)$ git branch -m new-name\n```\n\n現在いるブランチと異なる（ローカル）ブランチの名前を変更するには次のようにします。\n\n```sh\n(main)$ git branch -m old-name new-name\n```\n\n古い名前（`old-name`）のリモートブランチを削除し、新しい名前（`new-name`）のブランチをプッシュするには次の通りです。\n\n```sh\n(main)$ git push origin :old_name new_name\n```\n\n<a name=\"working-on-checkout-remote-branch\"></a>\n### 他の人が作業しているリモートブランチにチェックアウトしたい\n\nまず、リモートから全ブランチを取得します。\n\n```sh\n(main)$ git fetch --all\n```\n\nリモートブランチ `daves` にチェックアウトしたいとします。\n\n```sh\n(main)$ git checkout --track origin/daves\nBranch daves set up to track remote branch daves from origin.\nSwitched to a new branch 'daves'\n```\n\n（ここで `--track` は `git checkout -b [branch] [remotename]/[branch]` の短縮形です。）\n\nこれでローカルにブランチ `daves` のコピーが作成され、プッシュした編集がリモートに反映されるようになります。\n\n### 現在のローカルブランチをもとに新しいリモートブランチを作成したい\n\n```sh\n$ git push <remote> HEAD\n```\n\n同時にこのリモートブランチを現在のブランチの upstream に設定したい場合は、代わりに次を実行します。\n\n```sh\n$ git push -u <remote> HEAD\n```\n\n`push.default` の設定が `upstream` モードか `simple` モード（Git 2.0 のデフォルト）になっている場合、次を実行すると、以前に `-u` で登録したリモートブランチに現在のブランチをプッシュします。\n\n```sh\n$ git push\n```\n\n他のモードが `git push` でどう振る舞うかは、[`push.default` のドキュメント](https://git-scm.com/docs/git-config#Documentation/git-config.txt-pushdefault)で説明されています。\n\n### リモートブランチをローカルブランチの upstream に設定したい\n\n次のようにして、リモートブランチを現在いるローカルブランチの upstream に設定できます。\n\n```sh\n$ git branch --set-upstream-to [remotename]/[branch]\n# あるいは、短縮形を使う\n$ git branch -u [remotename]/[branch]\n```\n\n別のローカルブランチの upstream に設定するには次のようにします。\n\n```sh\n$ git branch -u [remotename]/[branch] [local-branch]\n```\n\n<a name=\"head-to-track-remote-branch\"></a>\n### 自分の HEAD をデフォルトのリモートブランチを追跡するよう設定したい\n\nリモートブランチを調べると、自分の HEAD がどのリモートブランチを追跡しているかがわかります。\nときどきこれが追跡したいブランチと異なることがあります。\n\n```sh\n$ git branch -r\n  origin/HEAD -> origin/gh-pages\n  origin/main\n```\n\n`origin/HEAD` が `origin/main` を追跡するよう設定し直すには、次を実行します。\n\n```sh\n$ git remote set-head origin --auto\norigin/HEAD set to main\n```\n\n### 間違ったブランチを編集してしまった\n\nまだコミットしていない編集を加えたあと、間違ったブランチにいることに気づいたとします。\n編集をスタッシュして、適切なブランチに適用すれば大丈夫です。\n\n```sh\n(wrong_branch)$ git stash\n(wrong_branch)$ git checkout <correct_branch>\n(correct_branch)$ git stash apply\n```\n\n## リベースとマージ\n\n<a name=\"undo-rebase\"></a>\n### リベースやマージを取り消したい\n\n現在のブランチを間違ったブランチにリベースないしマージしてしまった、あるいはリベースないしマージができなさそうだと気づいたとしましょう。\nGit は危険な操作の前に HEAD が指すものを変数 `ORIG_HEAD` に保存しているので、ブランチをリベースないしマージの前の状態に差し戻すのは簡単です。\n\n```sh\n(my-branch)$ git reset --hard ORIG_HEAD\n```\n\n<a name=\"force-push-rebase\"></a>\n### リベースしたが、強制プッシュはしたくない\n\n残念ながら、編集をリモートブランチに反映させるには強制プッシュをする必要があります。\n編集履歴を変えてしまったからです。\n強制プッシュしない限り、リモートブランチは編集を受け付けません。\nこれが多くの人がリベースワークフローではなくマージワークフローを使う主な理由です。\n特に大規模な開発チームは強制プッシュでハマりやすいです。\nリベースの強制プッシュは注意して使いましょう。\nリベースの安全な使い方は、リモートには編集を反映させずに、代わりに次を実行することです。\n\n```sh\n(main)$ git checkout my-branch\n(my-branch)$ git rebase -i main\n(my-branch)$ git checkout main\n(main)$ git merge --ff-only my-branch\n```\n\n詳しくは[この StackOverflow スレッド](https://stackoverflow.com/questions/11058312/how-can-i-use-git-rebase-without-requiring-a-forced-push)を参照してください。\n\n<a name=\"interactive-rebase\"></a>\n### コミットを統合したい\n\n`main` ブランチにプルリクエストを送る、あるいはこれから送るつもりのブランチで作業しているとします。\n最も単純なケースとして、タイムスタンプを気にせずコミット**全部**を一つにまとめたいとします。\nこの場合はリセットと再コミットを行います。\nマスターブランチが最新版で、編集がすべてコミットされていることを確認した上で、次を実行してください。\n\n```sh\n(my-branch)$ git reset --soft main\n(my-branch)$ git commit -am \"New awesome feature\"\n```\n\nもっと細かく設定し、タイムスタンプも残したい場合は、対話的リベースを使います。\n\n```sh\n(my-branch)$ git rebase -i main\n```\n\n別のブランチで作業しているわけではない場合、`HEAD` に対してリベースする必要があります。\nたとえば直近二件のコミットを圧縮 (squash) したい場合は `HEAD~2`、直近三件なら `HEAD~3` です。\n\n```sh\n(main)$ git rebase -i HEAD~2\n```\n\n対話的リベースのコマンドを実行したら、テキストエディタに次のように表示されます。\n\n```vim\npick a9c8a1d Some refactoring\npick 01b2fd8 New awesome feature\npick b729ad5 fixup\npick e3851e8 another fix\n\n# Rebase 8074d12..b729ad5 onto 8074d12\n#\n# Commands:\n#  p, pick = use commit\n#  r, reword = use commit, but edit the commit message\n#  e, edit = use commit, but stop for amending\n#  s, squash = use commit, but meld into previous commit\n#  f, fixup = like \"squash\", but discard this commit's log message\n#  x, exec = run command (the rest of the line) using shell\n#\n# These lines can be re-ordered; they are executed from top to bottom.\n#\n# If you remove a line here THAT COMMIT WILL BE LOST.\n#\n# However, if you remove everything, the rebase will be aborted.\n#\n# Note that empty commits are commented out\n```\n\nここで `#` から始まる行はコメントなので、リベースに影響しません。\n\nコマンド `pick` をリストの好きなコマンドで書きかえればよいです。\n行を削除すればコミットを削除できます。\n\n例えば、**一番古い（一番目の）コミットはそのまま残し、他のコミット全てを二番目のコミットに統合したい**場合は、最初と二番目以外のコミットの横の文字を `f` に書きかえます。\n\n```vim\npick a9c8a1d Some refactoring\npick 01b2fd8 New awesome feature\nf b729ad5 fixup\nf e3851e8 another fix\n```\n\nコミットを統合し、**さらに名前も変更したい**場合は、二番目のコミットの横にさらに `r` の文字を追加するか、あるいは単に `f` の代わりに `s` を使います。\n\n```vim\npick a9c8a1d Some refactoring\npick 01b2fd8 New awesome feature\ns b729ad5 fixup\ns e3851e8 another fix\n```\n\nするとテキストエディタが起動し、コミットの名前を変更できます。\n\n```vim\nNewer, awesomer features\n\n# Please enter the commit message for your changes. Lines starting\n# with '#' will be ignored, and an empty message aborts the commit.\n# rebase in progress; onto 8074d12\n# You are currently editing a commit while rebasing branch 'main' on '8074d12'.\n#\n# Changes to be committed:\n#   modified:   README.md\n#\n\n```\n\nうまくいくと次のように表示されるはずです。\n\n```sh\n(main)$ Successfully rebased and updated refs/heads/main.\n```\n\n#### 安全なマージの方法\n\nオプション `--no-commit` を指定すると、マージを実行しつつ、あたかもマージが失敗したかのように扱って自動コミットはしません。\nこれにより、コミットの前にマージの結果を精査したり調整できます。\nオプション `--no-ff` はフィーチャーブランチが存在したことを記録に残しておき、プロジェクト履歴の一貫性を保ちます。\n\n```sh\n(main)$ git merge --no-ff --no-commit my-branch\n```\n\n#### ブランチを一つのコミットにまとめたい場合\n\n```sh\n(main)$ git merge --squash my-branch\n```\n\n<a name=\"rebase-unpushed-commits\"></a>\n#### プッシュされていないコミットのみを統合したい場合\n\n進行中の作業に関するコミットがいくつかあって、upstream にコミットする前に統合しておきたいとします。\nすでに upstream にプッシュされたコミットは、誰かがそれを参照するコミットをしている可能性があるので、それは統合しないでおきたいとします。\n\n```sh\n(main)$ git rebase -i @{u}\n```\n\n上を実行すると対話的リベースが始まりますが、一覧にはまだプッシュされていないコミットだけが表示されます。\nこれで順番を入れ替えたり、修正したり、圧縮 (squash) したりしても安全です。\n\n#### マージを中止したい\n\nマージがファイルに問題をきたすことがあります。\nこういうときはオプション `abort` を使うとコンフリクト解消の作業を中止し、マージの前の状態の復元を試みることができます。\n\n```sh\n(my-branch)$ git merge --abort\n```\n\nただし、このコマンドが使えるのはバージョン 1.7.4 以上の Git に限ります。\n\n### ブランチの親コミットを更新したい\n\nマスターブランチとそこから分岐した feature-1 ブランチがあり、feature-1 からさらに分岐した feature-2 ブランチがあるとします。\nいま feature-1 ブランチにコミットしたとすると、feature-2 ブランチの親コミットはもはや正確ではありません（feature-1 から分岐したので、親コミットは feature-1 ブランチの head であるべきです。）\nこういうときは `git rebase --onto` で修正できます。\n\n```sh\n(feature-2)$ git rebase --onto feature-1 <the first commit in your feature-2 branch that you don't want to bring along> feature-2\n```\n\nまだマージされていないブランチからフィーチャーブランチを分岐させており、feature-1 ブランチのバグ修正を feature-2 に反映させたいときに便利です。\n\n### ブランチの全コミットがマージされているか確認する\n\nブランチの全コミットが別のブランチにマージされているか確認するには、それぞれのブランチの head（あるいは任意のコミット）の間の差分を表示します。\n\n```sh\n(main)$ git log --graph --left-right --cherry-pick --oneline HEAD...feature/120-on-scroll\n```\n\n一方のブランチにしかないコミットがあるか表示され、ブランチ間で共有されていないコミットの一覧がわかります。\nもう一つの方法は次の通りです。\n\n```sh\n(main)$ git log main ^feature/120-on-scroll --no-merges\n```\n\n### 対話的リベースで起こりうる問題\n\n<a name=\"noop\"></a>\n#### リベース編集画面に 'noop' と表示される\n\n次のように表示された場合です。\n\n```\nnoop\n```\n\nこれは、同じコミットのブランチ、あるいは現在のブランチよりも*先*にあるブランチに対してリベースしようとしたときに表示されます。\nこの場合は、\n\n* マスターブランチが正しい場所にあることを確認してください。\n* `HEAD~2` あるいはより以前にリベースしてください。\n\n<a name=\"merge-conflict\"></a>\n#### コンフリクトがあった\n\nリベースができないときは、解消すべきコンフリクトがあるかもしれません。\n\nまず `git status` で、どのファイルがコンフリクトを起こしているか確認します。\n\n```sh\n(my-branch)$ git status\nOn branch my-branch\nChanges not staged for commit:\n  (use \"git add <file>...\" to update what will be committed)\n  (use \"git checkout -- <file>...\" to discard changes in working directory)\n\n  both modified:   README.md\n```\n\nこの例では `README.md` にコンフリクトがあります。\nファイルを開き、次のようになっている箇所を見てみましょう。\n\n```vim\n   <<<<<<< HEAD\n   some code\n   =========\n   some code\n   >>>>>>> new-commit\n```\n\n`HEAD` と新しいコミットで加えられたコードの間の差分（この例では、真ん中の行から `new-commit` の間にあるコード）を解消する必要があります。\n\n一方のブランチの版のコードを残したい場合は、`--ours` あるいは `--theirs` を指定します。\n\n```sh\n(main*)$ git checkout --ours README.md\n```\n\n- *マージする*場合、ローカルブランチの編集を残したいとき `--ours` を指定し、他方の編集を残したいとき `--theirs` を指定します。\n- *リベースする*場合、ローカルブランチの編集を残したいとき `--theirs` を指定し、他方の編集を残したいとき `--ours` を指定します。このように逆転する理由は[ Git ドキュメントのこのノート](https://git-scm.com/docs/git-rebase#Documentation/git-rebase.txt---merge)を参照してください。\n\nマージがもっと複雑なときは、ビジュアル差分エディタを使うとよいです。\n\n```sh\n(main*)$ git mergetool -t opendiff\n```\n\nコンフリクトを全て解消し、コードのテストが済んだら、`git add ` で編集をステージし、`git rebase --continue` でリベースを再開します。\n\n```sh\n(my-branch)$ git add README.md\n(my-branch)$ git rebase --continue\n```\n\nコンフリクトを解消した結果、ワーキングツリーがコミット前と全く同じ状態になった場合は、代わりに `git rebase --skip` を実行します。\n\nリベース作業を全て中止し、ブランチを元の状態に差し戻したい場合は、次を実行します。\n\n```sh\n(my-branch)$ git rebase --abort\n```\n\n<a name=\"stashing\"></a>\n## スタッシュ\n\n### 全ての編集をスタッシュしたい\n\nワーキングディレクトリの編集を全てスタッシュするには、次を実行します。\n\n```sh\n$ git stash\n```\n\nバージョン管理されていないファイルもスタッシュしたいときは、オプション `-u` を指定します。\n\n```sh\n$ git stash -u\n```\n\n### 特定のファイルをスタッシュしたい\n\nワーキングディレクトリのファイル一つをスタッシュするには、次を実行します。\n\n```sh\n$ git stash push working-directory-path/filename.ext\n```\n\nワーキングディレクトリの複数のファイルをスタッシュするときは次の通りです。\n\n```sh\n$ git stash push working-directory-path/filename1.ext working-directory-path/filename2.ext\n```\n\n<a name=\"stash-msg\"></a>\n### メッセージをつけてスタッシュしたい\n\n```sh\n$ git stash save <message>\n```\n\nあるいは次の通りです。\n\n```sh\n$ git stash push -m <message>\n```\n\n<a name=\"stash-apply-specific\"></a>\n### 一覧から特定のスタッシュを選んで適用したい\n\nまず、次のようにしてスタッシュの一覧をメッセージとともに表示します。\n\n```sh\n$ git stash list\n```\n\nそして、次のようにして特定のスタッシュを選び適用します。\n\n```sh\n$ git stash apply \"stash@{n}\"\n```\n\nここで、`n` は一覧の中のスタッシュの位置を指します。一番上のスタッシュなら 0 番です。\n\nまた、時刻からスタッシュを指定することもできます。\n\n```sh\n$ git stash apply \"stash@{2.hours.ago}\"\n```\n\n<a name=\"stage-and-keep-unstaged\"></a>\n### ステージされていない編集をそのままにしつつ、スタッシュしたい\n\n手動で `stash commit` を作成し、`git stash store` を実行すればよいです。\n\n```sh\n$ git stash create\n$ git stash store -m <message> CREATED_SHA1\n```\n\n## 検索\n\n### 全コミットから文字列を検索したい\n\nどこかのコミットで導入された文字列を検索したいときは、次のコマンドを使います。\n\n```sh\n$ git log -S \"string to find\"\n```\n\nよく使われるパラメータは次の通りです。\n\n* `--source` はコマンドラインでつけられた各コミットの参照名を表示します。\n* `--all` は全てのブランチから検索します。\n* `--reverse` は逆順に表示します。すなわち最初のコミットから表示します。\n\n<a name=\"find-by-committer\"></a>\n### author または committer から検索する\n\n全てのコミットを author または committer の名前から検索するには次のようにします。\n\n```sh\n$ git log --author=<name or email>\n$ git log --committer=<name or email>\n```\n\nなお、author と committer は異なることに注意してください。\n`--author` ははじめにコードを書いた人、`--committer` は author の代わりにコミットした人を指します。\n\n### 特定のファイルを含むコミットの一覧を表示したい\n\n特定のファイルを含むコミットの一覧を表示するには、次を実行します。\n\n```sh\n$ git log -- <path to file>\n```\n\n通常は正確なパスを指定しますが、パスやファイル名にワイルドカードを使うこともできます。\n\n```sh\n$ git log -- **/*.js\n```\n\nワイルドカードを使う際は、`--name-status` を指定すると、コミットされたファイルの一覧が表示されて便利です。\n\n```sh\n$ git log --name-status -- **/*.js\n```\n\n<a name=\"view-commit-history-for-specific-function\"></a>\n### 特定の関数に関するコミット履歴を見たい\n\n特定の関数の履歴を追跡するには次を実行します。\n\n```sh\n$ git log -L :FunctionName:FilePath\n```\n\nこのコマンドは `git log` の他のオプション、例えば [revision ranges](https://git-scm.com/docs/gitrevisions) や [commit limits](https://git-scm.com/docs/git-log/#_commit_limiting) と一緒に使うことができます。\n\n### コミットが参照されているタグを検索したい\n\n特定のコミットを含むタグを検索するには次のようにします。\n\n```sh\n$ git tag --contains <commitid>\n```\n\n## サブモジュール\n\n<a name=\"clone-submodules\"></a>\n### 全てのサブモジュールをクローンする\n\n```sh\n$ git clone --recursive git://github.com/foo/bar.git\n```\n\nすでにクローンしている場合は次の通りです。\n\n```sh\n$ git submodule update --init --recursive\n```\n\n<a name=\"delete-submodule\"></a>\n### サブモジュールを削除する\n\nサブモジュールの作成はきわめて簡単ですが、削除はそうでもありません。\n削除に必要なコマンドは次の通りです。\n\n```sh\n$ git submodule deinit submodulename\n$ git rm submodulename\n$ git rm --cached submodulename\n$ rm -rf .git/modules/submodulename\n```\n\n## その他色々\n\n### あるブランチから別のブランチにフォルダをコピーしたい\n\n```sh\n$ git checkout <branch-you-want-the-directory-from> -- <folder-name or file-name>\n```\n\n### 削除されたファイルを復元したい\n\nまず、ファイルが最後に存在していたコミットを探します。\n\n```sh\n$ git rev-list -n 1 HEAD -- filename\n```\n\n見つけたら、ファイルをチェックアウトします。\n\n```\ngit checkout deletingcommitid^ -- filename\n```\n\n### タグを削除したい\n\n```sh\n$ git tag -d <tag_name>\n$ git push <remote> :refs/tags/<tag_name>\n```\n\n<a name=\"recover-tag\"></a>\n### 削除されたタグを復元したい\n\n削除されたタグを復元する手順は次の通りです。\nまず、unreachable になったタグを探します。\n\n```sh\n$ git fsck --unreachable | grep tag\n```\n\nタグのハッシュをメモしておきます。\n続いて、次のように [`git update-ref`](https://git-scm.com/docs/git-update-ref) で削除されたタグを復元します。\n\n```sh\n$ git update-ref refs/tags/<tag_name> <hash>\n```\n\nこれでタグが復元されたはずです。\n\n### 削除されたパッチを取得したい\n\n誰かが GitHub でプルリクエストを送ったあとにフォークを削除してしまった場合、そのリポジトリをクローンしたり、`git am` でパッチを適用することができなくなります。\n[.diff や .patch](https://github.com/blog/967-github-secrets) の URL が使えなくなってしまうためです。\nしかし、[GitHub 独自の参照](https://gist.github.com/piscisaureus/3342247)を使って、プルリクエスト自体をチェックアウトすることができます。\nプルリクエスト #1 の内容を新しいブランチ pr_1 に取得するには、次を実行します。\n\n```sh\n$ git fetch origin refs/pull/1/head:pr_1\nFrom github.com:foo/bar\n * [new ref]         refs/pull/1/head -> pr_1\n```\n\n### リポジトリを zip ファイルとしてエクスポートしたい\n\n```sh\n$ git archive --format zip --output /full/path/to/zipfile.zip main\n```\n\n### 同じ名前のブランチとタグをプッシュしたい\n\nブランチと同じ名前のタグがリモートリポジトリに存在する場合、通常通り `git push <remote> <branch>` でプッシュしようとすると、次のようなエラーが出ます。\n\n```sh\n$ git push origin <branch>\nerror: dst refspec same matches more than one.\nerror: failed to push some refs to '<git server>'\n```\n\nこのエラーはブランチのヘッドを指定することで回避できます。\n\n```sh\n$ git push origin refs/heads/<branch-name>\n```\n\n同名のブランチがリモートリポジトリにあるタグをプッシュしたいときも、似たコマンドを使います。\n\n```sh\n$ git push origin refs/tags/<tag-name>\n```\n\n## ファイルの追跡\n\n<a name=\"change-file-name-capitalization-without-changing-contents\"></a>\n### ファイルの内容は変えずに、ファイル名の大文字・小文字を変更したい\n\n```sh\n(main)$ git mv --force myfile MyFile\n```\n\n### git pull してローカルのファイルを上書きしたい\n\n```sh\n(main)$ git fetch --all\n(main)$ git reset --hard origin/main\n```\n\n<a name=\"remove-from-git\"></a>\n### ファイルを残しつつ Git から削除したい\n\n```sh\n(main)$ git rm --cached log.txt\n```\n\n### ファイルを特定の版まで差し戻したい\n\n差し戻したいコミットのハッシュが `c5f567` なら、次を実行します。\n\n```sh\n(main)$ git checkout c5f567 -- file1/to/restore file2/to/restore\n```\n\n差し戻したいコミットが c5f567 の一つ前なら、コミットハッシュに `c5f567~1` を指定します。\n\n```sh\n(main)$ git checkout c5f567~1 -- file1/to/restore file2/to/restore\n```\n\n### 特定のファイルのコミット間・ブランチ間の差分を表示したい\n\nコミット c5f567 とその一つ前の間の差分を表示したい場合、次を実行します。\n\n```sh\n$ git diff HEAD:path_to_file/file c5f567:path_to_file/file\n# または\n$ git diff HEAD c5f567 -- path_to_file/file\n```\n\nブランチでも同様です。\n\n```sh\n$ git diff main:path_to_file/file staging:path_to_file/file\n# または\n$ git diff main staging -- path_to_file/file\n```\n\n### 特定のファイルの変更を無視したい\n\nこれはローカル環境で設定テンプレートにコミットできない認証情報を追加する必要があるときなどに役立ちます。\n\n```sh\n$ git update-index --assume-unchanged file-to-ignore\n```\n\nファイルがバージョン管理されなくなるわけでは*ない*ことに注意してください。ローカルで無視されるだけです。\n設定を取り消して変更を再び追跡するには、次のように ignore フラッグを削除します。\n\n```sh\n$ git update-index --no-assume-unchanged file-to-stop-ignoring\n```\n\n## Git によるデバッグ\n\nコマンド [git-bisect](https://git-scm.com/docs/git-bisect) は、Git 履歴を二分探索してバグをもたらしたコミットを探します。\n\nいま `main` ブランチにいるとして、失敗をやらかしたコミットを探してみましょう。\n次のコマンドで二分探索を始めます。\n\n```sh\n$ git bisect start\n```\n\n問題のあるコミットとないコミットを指定する必要があります。\n*現在の*バージョンに問題があり、`v1.1.1` は問題ないとします。\n\n```sh\n$ git bisect bad\n$ git bisect good v1.1.1\n```\n\nすると、`git-bisect` は選んだバージョンの中間のコミットを選んで調べ、問題があるかどうか尋ねてきます。\n次のように表示されるはずです。\n\n```sh\n$ Bisecting: 5 revision left to test after this (roughly 5 step)\n$ [c44abbbee29cb93d8499283101fe7c8d9d97f0fe] Commit message\n$ (c44abbb)$\n```\n\nこのコミットに問題があるか調べましょう。\n問題がない (good) 場合は次を実行します。\n\n```sh\n$ (c44abbb)$ git bisect good\n```\n\nすると、`git-bisect` はまた別のコミットを選択します。\nこのように `good` か `bad` を選んでいく作業は、調べるコミットがなくなるまで続きます。\n終了したら、コマンドラインには問題をきたした**最初の**コミットの詳細が表示されます。\n\n## 設定\n\n### Git コマンドにエイリアスを設定したい\n\nOS X と Linux では、Git 設定ファイルは ```~/.gitconfig``` に保存されています。\n私の場合、ショートカット（とよくやるタイポ）のために次のようなものを ```[alias]``` セクションに設定しています。\n\n```vim\n[alias]\n    a = add\n    amend = commit --amend\n    c = commit\n    ca = commit --amend\n    ci = commit -a\n    co = checkout\n    d = diff\n    dc = diff --changed\n    ds = diff --staged\n    extend = commit --amend -C HEAD\n    f = fetch\n    loll = log --graph --decorate --pretty=oneline --abbrev-commit\n    m = merge\n    one = log --pretty=oneline\n    outstanding = rebase -i @{u}\n    reword = commit --amend --only\n    s = status\n    unpushed = log @{u}\n    wc = whatchanged\n    wip = rebase -i @{u}\n    zap = fetch -p\n    day = log --reverse --no-merges --branches=* --date=local --since=midnight --author=\\\"$(git config --get user.name)\\\"\n    delete-merged-branches = \"!f() { git checkout --quiet main && git branch --merged | grep --invert-match '\\\\*' | xargs -n 1 git branch --delete; git checkout --quiet @{-1}; }; f\"\n```\n\n### 空のディレクトリをリポジトリに加えたい\n\nできません！　Git ではできませんが、ハックする方法があります。\n次のような内容の .gitignore を作成してディレクトリに加えればよいです。\n\n```\n # Ignore everything in this directory\n *\n # Except this file\n !.gitignore\n```\n\nもう一つのよくある方法は、.gitkeep という名前の空のファイルをディレクトリに作成することです。\n\n```sh\n$ mkdir mydir\n$ touch mydir/.gitkeep\n```\n\n単に .keep という名前でもよいです。この場合、二行目は ```touch mydir/.keep``` とします。\n\n### リポジトリへのユーザ名とパスワードをキャッシュしたい\n\n認証が必要なリポジトリがあるとします。\nユーザ名とパスワードをキャッシュしておけば、プッシュやプルのたび入力せずに済みます。\n認証情報ヘルパーが役に立ちます。\n\n```sh\n$ git config --global credential.helper cache\n# Git が認証情報キャッシュを使うよう設定する\n```\n\n```sh\n$ git config --global credential.helper 'cache --timeout=3600'\n# キャッシュが一時間でタイムアウトするよう設定する（設定は秒単位）\n```\n\n認証情報ヘルパーを探すには、次を実行します。\n\n```sh\n$ git help -a | grep credential\n# 認証情報ヘルパーの候補が表示される\n```\n\nOS 固有の認証情報キャッシュは次の通りです。\n\n```sh\n$ git config --global credential.helper osxkeychain\n# OSX\n```\n\n```sh\n$ git config --global credential.helper manager\n# Git for Windows 2.7.3+\n```\n\n```sh\n$ git config --global credential.helper gnome-keyring\n# Ubuntu やその他の GNOME ベースディストリビューション\n```\n\nその他のディストリビューションや OS 向けの認証情報キャッシュもあります。\n\n### パーミッションとファイルモードの変更を Git が無視するようにしたい\n\n```sh\n$ git config core.fileMode false\n```\n\n\nこれをログインユーザ向けのデフォルト設定にしたい場合、次を実行します。\n\n```sh\n$ git config --global core.fileMode false\n```\n\n### グローバルユーザを設定したい\n\n全てのローカルリポジトリにわたるユーザ情報を設定し、バージョン履歴のレビューの際にわかりやすい名前を設定するには、次のようにします。\n\n```sh\n$ git config --global user.name “[firstname lastname]”\n```\n\n各履歴のマーカーに紐づけられるメールアドレスを設定したい場合は次の通りです。\n\n```sh\ngit config --global user.email “[valid-email]”\n```\n\n## 何を間違ったかわからないとき\n\n何かやらかした場合です。つまり、何かを `reset` してしまった、間違ったブランチをマージしてしまった、あるいは強制プッシュしてしまいコミットが見つけられない、といった状況です。\nある時点まではうまくいっていたので、その状態に戻したいとします。\n\nこうしたときに `git reflog` が役に立ちます。\n`reflog` は、ブランチが他のブランチやタグに参照されていなくても、ブランチになされた変更を記録しています。\nHEAD が変更される際は基本的に reflog に記録が追加されます。\nただ、残念ながら機能するのはローカルリポジトリのみで、記録するのは変化だけです（たとえば、どこにも記録されていないファイルへの変更は記録されません）。\n\n```sh\n(main)$ git reflog\n0a2e358 HEAD@{0}: reset: moving to HEAD~2\n0254ea7 HEAD@{1}: checkout: moving from 2.2 to main\nc10f740 HEAD@{2}: checkout: moving from main to 2.2\n```\n\n上の reflog には、main から 2.2 へのチェックアウトが表示されています。\nそれから古いコミットへの hard reset があります。\n最新のアクティビティは一番上に `HEAD@{0}` のラベルで表示されます。\n\n間違えて差し戻ししてしまったとします。\nコミット二つを間違って捨ててしまう前の、`0254ea7` を参照するコミットを reflog は保持しています。\n\n```sh\n$ git reset --hard 0254ea7\n```\n\nコマンド `git reset` を使って、マスターブランチを以前の状態に戻すことができます。\n履歴を間違えて変更してしまった場合の安全策です。\n\n（[出典](https://www.atlassian.com/git/tutorials/rewriting-history/git-reflog) からコピー・改変しました。）\n\n<a name=\"git-shortcuts\"></a>\n## Git ショートカット\n\n### Git Bash\n\n上記のコマンドに慣れてきたら、Git Bash のショートカットを作りたくなるはずです。\n複雑なタスクを短いコマンドで素早く行うことができるようになります。\n\n```sh\nalias sq=squash\n\nfunction squash() {\n    git rebase -i HEAD~$1\n}\n```\n\nこのコマンドを .bashrc か .bash_profile にコピーしてください。\n\n### Windows の PowerShell\n\nWindows で PowerShell を使っているなら、エイリアスや関数を作成できます。profile に次のコマンドを追加してください。\nprofile のパスは `$profile` に定義されています。詳しくは Microsoft のドキュメントサイトの [About Profiles](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_profiles) を参照してください。\n\n```powershell\nSet-Alias sq Squash-Commits\n\nfunction Squash-Commits {\n  git rebase -i HEAD~$1\n}\n```\n\n# 文献\n\n## 本\n\n* [Learn Enough Git to Be Dangerous](https://www.learnenough.com/git-tutorial) - Git の基礎からカバーした Michael Hartl の本\n* [Pro Git](https://git-scm.com/book/en/v2) - Scott Chacon と Ben Straub による Git に関する素晴らしい本\n* [Git Internals](https://github.com/pluralsight/git-internals-pdf) - Scott Chacon による Git に関する素晴らしい本\n* [Nasa handbook](https://www.nasa.gov/sites/default/files/atoms/files/nasa_systems_engineering_handbook.pdf)\n\n## チュートリアル\n\n* [19 Git Tips For Everyday Use](https://www.alexkras.com/19-git-tips-for-everyday-use) - Git の便利なワンライナーの一覧\n* [Atlassian's Git tutorial](https://www.atlassian.com/git/tutorials) - 初心者から上級者までチュートリアルで Git を正しく使おう\n* [Learn Git branching](https://learngitbranching.js.org/) - web で動くブランチ・マージ・リベースの対話的なチュートリアル\n* [Getting solid at Git rebase vs. merge](https://medium.com/@porteneuve/getting-solid-at-git-rebase-vs-merge-4fa1a48c53aa)\n* [Git Commands and Best Practices Cheat Sheet](https://zeroturnaround.com/rebellabs/git-commands-and-best-practices-cheat-sheet) - ブログ投稿にあるもっと説明の豊富な Git チートシート\n* [Git from the inside out](https://codewords.recurse.com/issues/two/git-from-the-inside-out) - Git の内部に踏み込んだチュートリアル\n* [git-workflow](https://github.com/asmeurer/git-workflow) - [Aaron Meurer](https://github.com/asmeurer) による Git を使ってオープンソースリポジトリに貢献する方法の解説\n* [GitHub as a workflow](https://hugogiraudel.com/2015/08/13/github-as-a-workflow/) - GitHub を、特に空のプルリクエストを用いてワークフローとして使う面白い試み\n* [Githug](https://github.com/Gazler/githug) - よく使う Git ワークフローを学ぶゲーム\n* [learnGitBranching](https://github.com/pcottle/learnGitBranching) - 刺激を得たり教育に使える git の可視化\n\n## スクリプトとツール\n\n* [firstaidgit.io](http://firstaidgit.io/) - 検索可能な Git のよくある質問集\n* [git-extra-commands](https://github.com/unixorn/git-extra-commands) - 便利な Git スクリプトのコレクション\n* [git-extras](https://github.com/tj/git-extras) - Git の 便利機能 -- リポジトリの要約、REPL、編集履歴の人口、開発者ごとのコミット率など\n* [git-fire](https://github.com/qw3rtman/git-fire) - 緊急時に（マージのコンフリクトを防ぐため）新しいブランチに全ファイルを追加・コミット・プッシュする Git のプラグイン\n* [git-tips](https://github.com/git-tips/tips) - ちょっとした Git のコツ\n* [git-town](https://github.com/Originate/git-town) - 一般的でハイレベルな Git ワークフローのサポート http://www.git-town.com\n\n## GUI クライアント\n* [GitKraken](https://www.gitkraken.com/) - Windows, Mac, Linux 向けの真正で豪華な Git クライアント\n* [git-cola](https://git-cola.github.io/) - Windows と OS X 向けのもう一つの Git クライアント\n* [GitUp](https://github.com/git-up/GitUp) - Git の問題に対処する志向の強い方法をそなえた新しい GUI クライアント\n* [gitx-dev](https://rowanj.github.io/gitx/) - OS X 向けのグラフィカル Git クライアント\n* [Sourcetree](https://www.sourcetreeapp.com/) - シンプルさと強力さを兼ね備えた Windows と Mac 向けの美しい Git GUI です。で動きます。\n* [Tower](https://www.git-tower.com/) - OS X で動くグラフィカル Git クライアント（有料）\n* [tig](https://jonas.github.io/tig/) - Git のターミナルテキストモードインターフェース\n* [Magit](https://magit.vc/) - Emacs のパッケージとして実装された Git のインターフェース\n* [GitExtensions](https://github.com/gitextensions/gitextensions) - シェル拡張・Visual Studio 2010-2015 プラグイン・スタンドアローンの Git リポジトリツール\n* [Fork](https://git-fork.com/) - Mac で動く高速で使いやすい Git クライアント（ベータ版）\n* [gmaster](https://gmaster.io/) - Windows で動く、三者間マージ、リファクタリング解析、セマンティック差分とマージのできる Git クライアント（ベータ版）\n* [gitk](https://git-scm.com/docs/gitk) - Linux 向けのリポジトリの状態をシンプルに見られる Git クライアント\n* [SublimeMerge](https://www.sublimemerge.com/) - 三者間マージ・強力な検索機能・シンタックスハイライトをそなえた驚異的に高速で拡張性の高いクライアント。活発に開発されている\n"
  },
  {
    "path": "README_kr.md",
    "content": "# 깃을 위한 flight rules\n\n🌍\n*[English](README.md) ∙ [Español](README_es.md)  ∙  [Русский](README_ru.md) ∙ [繁體中文](README_zh-TW.md) ∙ [简体中文](README_zh-CN.md) ∙ [한국어](README_kr.md)  ∙  [Tiếng Việt](README_vi.md) ∙ [Français](README_fr.md) ∙ [日本語](README_ja.md)*\n\n#### flight rules 가 뭐야?\n\n뭔가 잘못 됐을 때 뭘 해야할지에 대한 우주비행사를 위한 가이드 (여기선 깃을 쓰는 개발자를 위한)\n\n\n>  *Flight Rules* 는 어떤 문제 X가 발생한 이유와 그 단계의 매뉴얼에서 어렵사리 얻은 지식이에요. 기본적으로 각 시나리오의 매우 자세하고 구체적인 운영 절차랍니다. [...]\n\n> NASA는 수성(Mercury) 시대 때 지상팀에서 처음으로 \"lessons learned\" 이란 것을 모았는데 수천개의 문제의 상황들, 부서진 해치 손잡이로 인한 엔진 고장부터 컴퓨터 문제 그리고 그 해답까지, 1960년대 초부터 우리의 실수들, 재앙들, 해결책 등이  목록화 돼있어요.\n\n— Chris Hadfield, *인생을 위한 우주비행사의 가이드*.\n\n#### 이 문서의 규칙\n\n명확하게 하기 위해 이 문서의 모든 예제는 현재 브랜치를 표시하고 스테이지에 변경이 있는지를 나타내기 위해 커스텀 된 배시 프롬프트를 써요. 브랜치는 괄호 안에 있고, 브랜치 다음의 *는 스테이지의 변경된 것을 나타내요.\n\n[![Join the chat at https://gitter.im/k88hudson/git-flight-rules](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/k88hudson/git-flight-rules?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n  - [레파지토리](#%EB%A0%88%ED%8C%8C%EC%A7%80%ED%86%A0%EB%A6%AC)\n    - [로컬 레파지토리에서 시작하고 싶어](#%EB%A1%9C%EC%BB%AC-%EB%A0%88%ED%8C%8C%EC%A7%80%ED%86%A0%EB%A6%AC%EC%97%90%EC%84%9C-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n    - [난 리모트 레파지토리를 복제해오고 싶어](#%EB%82%9C-%EB%A6%AC%EB%AA%A8%ED%8A%B8-%EB%A0%88%ED%8C%8C%EC%A7%80%ED%86%A0%EB%A6%AC%EB%A5%BC-%EB%B3%B5%EC%A0%9C%ED%95%B4%EC%98%A4%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n  - [커밋 수정](#%EC%BB%A4%EB%B0%8B-%EC%88%98%EC%A0%95)\n    - [내가 방금 어떤 커밋을 남겼지?](#%EB%82%B4%EA%B0%80-%EB%B0%A9%EA%B8%88-%EC%96%B4%EB%96%A4-%EC%BB%A4%EB%B0%8B%EC%9D%84-%EB%82%A8%EA%B2%BC%EC%A7%80)\n    - [커밋 메세지를 잘못 썼어](#%EC%BB%A4%EB%B0%8B-%EB%A9%94%EC%84%B8%EC%A7%80%EB%A5%BC-%EC%9E%98%EB%AA%BB-%EC%8D%BC%EC%96%B4)\n    - [커밋을 다른 이름과 이메일 설정으로 해버렸어](#%EC%BB%A4%EB%B0%8B%EC%9D%84-%EB%8B%A4%EB%A5%B8-%EC%9D%B4%EB%A6%84%EA%B3%BC-%EC%9D%B4%EB%A9%94%EC%9D%BC-%EC%84%A4%EC%A0%95%EC%9C%BC%EB%A1%9C-%ED%95%B4%EB%B2%84%EB%A0%B8%EC%96%B4)\n    - [지난 커밋에서 파일 하나를 지우고 싶어](#%EC%A7%80%EB%82%9C-%EC%BB%A4%EB%B0%8B%EC%97%90%EC%84%9C-%ED%8C%8C%EC%9D%BC-%ED%95%98%EB%82%98%EB%A5%BC-%EC%A7%80%EC%9A%B0%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n    - [마지막 커밋을 지우고 싶어](#%EB%A7%88%EC%A7%80%EB%A7%89-%EC%BB%A4%EB%B0%8B%EC%9D%84-%EC%A7%80%EC%9A%B0%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n    - [임의적인 커밋 지우기](#%EC%9E%84%EC%9D%98%EC%A0%81%EC%9D%B8-%EC%BB%A4%EB%B0%8B-%EC%A7%80%EC%9A%B0%EA%B8%B0)\n    - [수정된 커밋을 푸시했는데, 에러 메세지가 떠](#%EC%88%98%EC%A0%95%EB%90%9C-%EC%BB%A4%EB%B0%8B%EC%9D%84-%ED%91%B8%EC%8B%9C%ED%96%88%EB%8A%94%EB%8D%B0-%EC%97%90%EB%9F%AC-%EB%A9%94%EC%84%B8%EC%A7%80%EA%B0%80-%EB%96%A0)\n    - [하드 리셋을 해버렸는데 되돌리고 싶어](#%ED%95%98%EB%93%9C-%EB%A6%AC%EC%85%8B%EC%9D%84-%ED%95%B4%EB%B2%84%EB%A0%B8%EB%8A%94%EB%8D%B0-%EB%90%98%EB%8F%8C%EB%A6%AC%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n    - [머지를 실수로 커밋, 푸시해버렸어](#%EB%A8%B8%EC%A7%80%EB%A5%BC-%EC%8B%A4%EC%88%98%EB%A1%9C-%EC%BB%A4%EB%B0%8B-%ED%91%B8%EC%8B%9C%ED%95%B4%EB%B2%84%EB%A0%B8%EC%96%B4)\n  - [스테이지](#%EC%8A%A4%ED%85%8C%EC%9D%B4%EC%A7%80)\n    - [지난 커밋에 스테이지 변경점을 추가하고 싶어](#%EC%A7%80%EB%82%9C-%EC%BB%A4%EB%B0%8B%EC%97%90-%EC%8A%A4%ED%85%8C%EC%9D%B4%EC%A7%80-%EB%B3%80%EA%B2%BD%EC%A0%90%EC%9D%84-%EC%B6%94%EA%B0%80%ED%95%98%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n    - [전체가 아닌 새 파일만 스테이지에 올리고 싶어](#%EC%A0%84%EC%B2%B4%EA%B0%80-%EC%95%84%EB%8B%8C-%EC%83%88-%ED%8C%8C%EC%9D%BC%EB%A7%8C-%EC%8A%A4%ED%85%8C%EC%9D%B4%EC%A7%80%EC%97%90-%EC%98%AC%EB%A6%AC%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n    - [하나의 파일 변경점을 두개의 다른 커밋에 남기고 싶어](#%ED%95%98%EB%82%98%EC%9D%98-%ED%8C%8C%EC%9D%BC-%EB%B3%80%EA%B2%BD%EC%A0%90%EC%9D%84-%EB%91%90%EA%B0%9C%EC%9D%98-%EB%8B%A4%EB%A5%B8-%EC%BB%A4%EB%B0%8B%EC%97%90-%EB%82%A8%EA%B8%B0%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n    - [아직 스테이지에 안 올라간 변경점을 스테이지에 추가하고, 스테이지에 있는 변경점을 다시 빼고 싶어](#%EC%95%84%EC%A7%81-%EC%8A%A4%ED%85%8C%EC%9D%B4%EC%A7%80%EC%97%90-%EC%95%88-%EC%98%AC%EB%9D%BC%EA%B0%84-%EB%B3%80%EA%B2%BD%EC%A0%90%EC%9D%84-%EC%8A%A4%ED%85%8C%EC%9D%B4%EC%A7%80%EC%97%90-%EC%B6%94%EA%B0%80%ED%95%98%EA%B3%A0-%EC%8A%A4%ED%85%8C%EC%9D%B4%EC%A7%80%EC%97%90-%EC%9E%88%EB%8A%94-%EB%B3%80%EA%B2%BD%EC%A0%90%EC%9D%84-%EB%8B%A4%EC%8B%9C-%EB%B9%BC%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n  - [스테이지 전의 변경점](#%EC%8A%A4%ED%85%8C%EC%9D%B4%EC%A7%80-%EC%A0%84%EC%9D%98-%EB%B3%80%EA%B2%BD%EC%A0%90)\n    - [스테이지 전의 변경점을 새 브랜치로 옮기고 싶어](#%EC%8A%A4%ED%85%8C%EC%9D%B4%EC%A7%80-%EC%A0%84%EC%9D%98-%EB%B3%80%EA%B2%BD%EC%A0%90%EC%9D%84-%EC%83%88-%EB%B8%8C%EB%9E%9C%EC%B9%98%EB%A1%9C-%EC%98%AE%EA%B8%B0%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n    - [스테이지전 변경점을 만들어둔 다른 브랜치로 옮기고 싶어](#%EC%8A%A4%ED%85%8C%EC%9D%B4%EC%A7%80%EC%A0%84-%EB%B3%80%EA%B2%BD%EC%A0%90%EC%9D%84-%EB%A7%8C%EB%93%A4%EC%96%B4%EB%91%94-%EB%8B%A4%EB%A5%B8-%EB%B8%8C%EB%9E%9C%EC%B9%98%EB%A1%9C-%EC%98%AE%EA%B8%B0%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n    - [내 로컬에 있는 커밋 안된 변경점을 다 무시하고 싶어 (스테이징 됐던 안됐던)](#%EB%82%B4-%EB%A1%9C%EC%BB%AC%EC%97%90-%EC%9E%88%EB%8A%94-%EC%BB%A4%EB%B0%8B-%EC%95%88%EB%90%9C-%EB%B3%80%EA%B2%BD%EC%A0%90%EC%9D%84-%EB%8B%A4-%EB%AC%B4%EC%8B%9C%ED%95%98%EA%B3%A0-%EC%8B%B6%EC%96%B4-%EC%8A%A4%ED%85%8C%EC%9D%B4%EC%A7%95-%EB%90%90%EB%8D%98-%EC%95%88%EB%90%90%EB%8D%98)\n    - [스테이지 안된 특정 변경점을 지우고 싶어](#%EC%8A%A4%ED%85%8C%EC%9D%B4%EC%A7%80-%EC%95%88%EB%90%9C-%ED%8A%B9%EC%A0%95-%EB%B3%80%EA%B2%BD%EC%A0%90%EC%9D%84-%EC%A7%80%EC%9A%B0%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n    - [스테이지 안된 특정 파일을 지우고 싶어](#%EC%8A%A4%ED%85%8C%EC%9D%B4%EC%A7%80-%EC%95%88%EB%90%9C-%ED%8A%B9%EC%A0%95-%ED%8C%8C%EC%9D%BC%EC%9D%84-%EC%A7%80%EC%9A%B0%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n    - [로컬에 있는 스테이지 안된 변경점만 지우고 싶어](#%EB%A1%9C%EC%BB%AC%EC%97%90-%EC%9E%88%EB%8A%94-%EC%8A%A4%ED%85%8C%EC%9D%B4%EC%A7%80-%EC%95%88%EB%90%9C-%EB%B3%80%EA%B2%BD%EC%A0%90%EB%A7%8C-%EC%A7%80%EC%9A%B0%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n    - [트래킹 안된 파일들 다 지우고 싶어](#%ED%8A%B8%EB%9E%98%ED%82%B9-%EC%95%88%EB%90%9C-%ED%8C%8C%EC%9D%BC%EB%93%A4-%EB%8B%A4-%EC%A7%80%EC%9A%B0%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n  - [브랜치](#%EB%B8%8C%EB%9E%9C%EC%B9%98)\n    - [모든 브랜치 리스트를 보고 싶어](#%EB%AA%A8%EB%93%A0-%EB%B8%8C%EB%9E%9C%EC%B9%98-%EB%A6%AC%EC%8A%A4%ED%8A%B8%EB%A5%BC-%EB%B3%B4%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n    - [커밋에서 브랜치 만들기](#%EC%BB%A4%EB%B0%8B%EC%97%90%EC%84%9C-%EB%B8%8C%EB%9E%9C%EC%B9%98-%EB%A7%8C%EB%93%A4%EA%B8%B0)\n    - [다른 브랜치에서 풀을 받아와버렸어](#%EB%8B%A4%EB%A5%B8-%EB%B8%8C%EB%9E%9C%EC%B9%98%EC%97%90%EC%84%9C-%ED%92%80%EC%9D%84-%EB%B0%9B%EC%95%84%EC%99%80%EB%B2%84%EB%A0%B8%EC%96%B4)\n    - [로컬의 커밋을 지워서 서버에 있는 내 브랜치와 맞추고 싶어](#%EB%A1%9C%EC%BB%AC%EC%9D%98-%EC%BB%A4%EB%B0%8B%EC%9D%84-%EC%A7%80%EC%9B%8C%EC%84%9C-%EC%84%9C%EB%B2%84%EC%97%90-%EC%9E%88%EB%8A%94-%EB%82%B4-%EB%B8%8C%EB%9E%9C%EC%B9%98%EC%99%80-%EB%A7%9E%EC%B6%94%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n    - [새 브랜치 대신에 마스터에 커밋을 해버렸어](#%EC%83%88-%EB%B8%8C%EB%9E%9C%EC%B9%98-%EB%8C%80%EC%8B%A0%EC%97%90-%EB%A7%88%EC%8A%A4%ED%84%B0%EC%97%90-%EC%BB%A4%EB%B0%8B%EC%9D%84-%ED%95%B4%EB%B2%84%EB%A0%B8%EC%96%B4)\n    - [다른 레퍼런스 같은 곳에서 모든 파일을 유지하고 싶어](#%EB%8B%A4%EB%A5%B8-%EB%A0%88%ED%8D%BC%EB%9F%B0%EC%8A%A4-%EA%B0%99%EC%9D%80-%EA%B3%B3%EC%97%90%EC%84%9C-%EB%AA%A8%EB%93%A0-%ED%8C%8C%EC%9D%BC%EC%9D%84-%EC%9C%A0%EC%A7%80%ED%95%98%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n    - [한 브랜치에 다른 브랜치에 남겼어야 하는 커밋을 여러개 남겼어](#%ED%95%9C-%EB%B8%8C%EB%9E%9C%EC%B9%98%EC%97%90-%EB%8B%A4%EB%A5%B8-%EB%B8%8C%EB%9E%9C%EC%B9%98%EC%97%90-%EB%82%A8%EA%B2%BC%EC%96%B4%EC%95%BC-%ED%95%98%EB%8A%94-%EC%BB%A4%EB%B0%8B%EC%9D%84-%EC%97%AC%EB%9F%AC%EA%B0%9C-%EB%82%A8%EA%B2%BC%EC%96%B4)\n    - [업스트림에선 지워진 로컬 브랜치를 지우고 싶어](#%EC%97%85%EC%8A%A4%ED%8A%B8%EB%A6%BC%EC%97%90%EC%84%A0-%EC%A7%80%EC%9B%8C%EC%A7%84-%EB%A1%9C%EC%BB%AC-%EB%B8%8C%EB%9E%9C%EC%B9%98%EB%A5%BC-%EC%A7%80%EC%9A%B0%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n    - [브랜치를 지워버렸어](#%EB%B8%8C%EB%9E%9C%EC%B9%98%EB%A5%BC-%EC%A7%80%EC%9B%8C%EB%B2%84%EB%A0%B8%EC%96%B4)\n    - [브랜치를 지우고 싶어](#%EB%B8%8C%EB%9E%9C%EC%B9%98%EB%A5%BC-%EC%A7%80%EC%9A%B0%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n    - [여러개의 브랜치를 지우고 싶어](#%EC%97%AC%EB%9F%AC%EA%B0%9C%EC%9D%98-%EB%B8%8C%EB%9E%9C%EC%B9%98%EB%A5%BC-%EC%A7%80%EC%9A%B0%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n    - [브랜치 이름을 바꾸고 싶어](#%EB%B8%8C%EB%9E%9C%EC%B9%98-%EC%9D%B4%EB%A6%84%EC%9D%84-%EB%B0%94%EA%BE%B8%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n    - [다른 사람이 작업중인 리모트 브랜치로 체크아웃 하고 싶어](#%EB%8B%A4%EB%A5%B8-%EC%82%AC%EB%9E%8C%EC%9D%B4-%EC%9E%91%EC%97%85%EC%A4%91%EC%9D%B8-%EB%A6%AC%EB%AA%A8%ED%8A%B8-%EB%B8%8C%EB%9E%9C%EC%B9%98%EB%A1%9C-%EC%B2%B4%ED%81%AC%EC%95%84%EC%9B%83-%ED%95%98%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n    - [현재 로컬 브랜치로 새로운 리모트 브랜치를 만들고 싶어](#%ED%98%84%EC%9E%AC-%EB%A1%9C%EC%BB%AC-%EB%B8%8C%EB%9E%9C%EC%B9%98%EB%A1%9C-%EC%83%88%EB%A1%9C%EC%9A%B4-%EB%A6%AC%EB%AA%A8%ED%8A%B8-%EB%B8%8C%EB%9E%9C%EC%B9%98%EB%A5%BC-%EB%A7%8C%EB%93%A4%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n    - [리모트 브랜치를 로컬 브랜치를 위한 업스트림으로 설정하고 싶어](#%EB%A6%AC%EB%AA%A8%ED%8A%B8-%EB%B8%8C%EB%9E%9C%EC%B9%98%EB%A5%BC-%EB%A1%9C%EC%BB%AC-%EB%B8%8C%EB%9E%9C%EC%B9%98%EB%A5%BC-%EC%9C%84%ED%95%9C-%EC%97%85%EC%8A%A4%ED%8A%B8%EB%A6%BC%EC%9C%BC%EB%A1%9C-%EC%84%A4%EC%A0%95%ED%95%98%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n    - [HEAD를 기본 리모트 브랜치로 트래킹하도록 설정하고 싶어](#head%EB%A5%BC-%EA%B8%B0%EB%B3%B8-%EB%A6%AC%EB%AA%A8%ED%8A%B8-%EB%B8%8C%EB%9E%9C%EC%B9%98%EB%A1%9C-%ED%8A%B8%EB%9E%98%ED%82%B9%ED%95%98%EB%8F%84%EB%A1%9D-%EC%84%A4%EC%A0%95%ED%95%98%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n    - [다른 브랜치에 변경점을 잘못 남겼어](#%EB%8B%A4%EB%A5%B8-%EB%B8%8C%EB%9E%9C%EC%B9%98%EC%97%90-%EB%B3%80%EA%B2%BD%EC%A0%90%EC%9D%84-%EC%9E%98%EB%AA%BB-%EB%82%A8%EA%B2%BC%EC%96%B4)\n  - [리베이스와 머지](#%EB%A6%AC%EB%B2%A0%EC%9D%B4%EC%8A%A4%EC%99%80-%EB%A8%B8%EC%A7%80)\n    - [리베이스/머지 한 걸 되돌리고 싶어](#%EB%A6%AC%EB%B2%A0%EC%9D%B4%EC%8A%A4%EB%A8%B8%EC%A7%80-%ED%95%9C-%EA%B1%B8-%EB%90%98%EB%8F%8C%EB%A6%AC%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n    - [리베이스를 했는데, 강제 푸시하고 싶진 않아](#%EB%A6%AC%EB%B2%A0%EC%9D%B4%EC%8A%A4%EB%A5%BC-%ED%96%88%EB%8A%94%EB%8D%B0-%EA%B0%95%EC%A0%9C-%ED%91%B8%EC%8B%9C%ED%95%98%EA%B3%A0-%EC%8B%B6%EC%A7%84-%EC%95%8A%EC%95%84)\n    - [커밋끼리 합치고 싶어](#%EC%BB%A4%EB%B0%8B%EB%81%BC%EB%A6%AC-%ED%95%A9%EC%B9%98%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n      - [안전한 머지 전략](#%EC%95%88%EC%A0%84%ED%95%9C-%EB%A8%B8%EC%A7%80-%EC%A0%84%EB%9E%B5)\n      - [브랜치를 커밋 하나로 머지해야해](#%EB%B8%8C%EB%9E%9C%EC%B9%98%EB%A5%BC-%EC%BB%A4%EB%B0%8B-%ED%95%98%EB%82%98%EB%A1%9C-%EB%A8%B8%EC%A7%80%ED%95%B4%EC%95%BC%ED%95%B4)\n      - [푸시 되지 않은 커밋만 합치고 싶어](#%ED%91%B8%EC%8B%9C-%EB%90%98%EC%A7%80-%EC%95%8A%EC%9D%80-%EC%BB%A4%EB%B0%8B%EB%A7%8C-%ED%95%A9%EC%B9%98%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n      - [머지를 중단해야해](#%EB%A8%B8%EC%A7%80%EB%A5%BC-%EC%A4%91%EB%8B%A8%ED%95%B4%EC%95%BC%ED%95%B4)\n    - [브랜치내 모든 커밋이 머지됐는지 확인해](#%EB%B8%8C%EB%9E%9C%EC%B9%98%EB%82%B4-%EB%AA%A8%EB%93%A0-%EC%BB%A4%EB%B0%8B%EC%9D%B4-%EB%A8%B8%EC%A7%80%EB%90%90%EB%8A%94%EC%A7%80-%ED%99%95%EC%9D%B8%ED%95%B4)\n    - [대화형 리베이스로 발생가능한 이슈](#%EB%8C%80%ED%99%94%ED%98%95-%EB%A6%AC%EB%B2%A0%EC%9D%B4%EC%8A%A4%EB%A1%9C-%EB%B0%9C%EC%83%9D%EA%B0%80%EB%8A%A5%ED%95%9C-%EC%9D%B4%EC%8A%88)\n      - [리베이스 편집 화면에서 'noop'](#%EB%A6%AC%EB%B2%A0%EC%9D%B4%EC%8A%A4-%ED%8E%B8%EC%A7%91-%ED%99%94%EB%A9%B4%EC%97%90%EC%84%9C-noop)\n      - [충돌이 있어](#%EC%B6%A9%EB%8F%8C%EC%9D%B4-%EC%9E%88%EC%96%B4)\n  - [스테이시](#%EC%8A%A4%ED%85%8C%EC%9D%B4%EC%8B%9C)\n    - [모든 변경점 스테이시 하기](#%EB%AA%A8%EB%93%A0-%EB%B3%80%EA%B2%BD%EC%A0%90-%EC%8A%A4%ED%85%8C%EC%9D%B4%EC%8B%9C-%ED%95%98%EA%B8%B0)\n    - [특정 파일들만 스테이시 하기](#%ED%8A%B9%EC%A0%95-%ED%8C%8C%EC%9D%BC%EB%93%A4%EB%A7%8C-%EC%8A%A4%ED%85%8C%EC%9D%B4%EC%8B%9C-%ED%95%98%EA%B8%B0)\n    - [메세지와 함께 스테이시 하기](#%EB%A9%94%EC%84%B8%EC%A7%80%EC%99%80-%ED%95%A8%EA%BB%98-%EC%8A%A4%ED%85%8C%EC%9D%B4%EC%8B%9C-%ED%95%98%EA%B8%B0)\n    - [특정 스테이시 목록에서 가져와 적용하기](#%ED%8A%B9%EC%A0%95-%EC%8A%A4%ED%85%8C%EC%9D%B4%EC%8B%9C-%EB%AA%A9%EB%A1%9D%EC%97%90%EC%84%9C-%EA%B0%80%EC%A0%B8%EC%99%80-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0)\n  - [찾아보기](#%EC%B0%BE%EC%95%84%EB%B3%B4%EA%B8%B0)\n    - [어떤 커밋에서 문자열을 찾고 싶어](#%EC%96%B4%EB%96%A4-%EC%BB%A4%EB%B0%8B%EC%97%90%EC%84%9C-%EB%AC%B8%EC%9E%90%EC%97%B4%EC%9D%84-%EC%B0%BE%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n    - [작성자나 커미터를 찾고 싶어](#%EC%9E%91%EC%84%B1%EC%9E%90%EB%82%98-%EC%BB%A4%EB%AF%B8%ED%84%B0%EB%A5%BC-%EC%B0%BE%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n    - [특정 파일이 포함된 커밋을 목록화 하고 싶어](#%ED%8A%B9%EC%A0%95-%ED%8C%8C%EC%9D%BC%EC%9D%B4-%ED%8F%AC%ED%95%A8%EB%90%9C-%EC%BB%A4%EB%B0%8B%EC%9D%84-%EB%AA%A9%EB%A1%9D%ED%99%94-%ED%95%98%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n    - [커밋을 참조하는 태그를 찾고 싶어](#%EC%BB%A4%EB%B0%8B%EC%9D%84-%EC%B0%B8%EC%A1%B0%ED%95%98%EB%8A%94-%ED%83%9C%EA%B7%B8%EB%A5%BC-%EC%B0%BE%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n  - [서브모듈](#%EC%84%9C%EB%B8%8C%EB%AA%A8%EB%93%88)\n    - [모든 서브모듈을 클론하기](#%EB%AA%A8%EB%93%A0-%EC%84%9C%EB%B8%8C%EB%AA%A8%EB%93%88%EC%9D%84-%ED%81%B4%EB%A1%A0%ED%95%98%EA%B8%B0)\n    - [서브모듈 지우기](#%EC%84%9C%EB%B8%8C%EB%AA%A8%EB%93%88-%EC%A7%80%EC%9A%B0%EA%B8%B0)\n  - [기타 항목들](#%EA%B8%B0%ED%83%80-%ED%95%AD%EB%AA%A9%EB%93%A4)\n    - [지운 파일 복구하기](#%EC%A7%80%EC%9A%B4-%ED%8C%8C%EC%9D%BC-%EB%B3%B5%EA%B5%AC%ED%95%98%EA%B8%B0)\n    - [태그 지우기](#%ED%83%9C%EA%B7%B8-%EC%A7%80%EC%9A%B0%EA%B8%B0)\n    - [지워진 태그 복구하기](#%EC%A7%80%EC%9B%8C%EC%A7%84-%ED%83%9C%EA%B7%B8-%EB%B3%B5%EA%B5%AC%ED%95%98%EA%B8%B0)\n    - [지워진 패치](#%EC%A7%80%EC%9B%8C%EC%A7%84-%ED%8C%A8%EC%B9%98)\n    - [Zip파일로 레파지토리 추출하기](#zip%ED%8C%8C%EC%9D%BC%EB%A1%9C-%EB%A0%88%ED%8C%8C%EC%A7%80%ED%86%A0%EB%A6%AC-%EC%B6%94%EC%B6%9C%ED%95%98%EA%B8%B0)\n  - [파일 추적하기](#%ED%8C%8C%EC%9D%BC-%EC%B6%94%EC%A0%81%ED%95%98%EA%B8%B0)\n    - [파일 내용엔 변경이 없이 파일 이름을 앞글자만 대문자로 바꾸고 싶어](#%ED%8C%8C%EC%9D%BC-%EB%82%B4%EC%9A%A9%EC%97%94-%EB%B3%80%EA%B2%BD%EC%9D%B4-%EC%97%86%EC%9D%B4-%ED%8C%8C%EC%9D%BC-%EC%9D%B4%EB%A6%84%EC%9D%84-%EC%95%9E%EA%B8%80%EC%9E%90%EB%A7%8C-%EB%8C%80%EB%AC%B8%EC%9E%90%EB%A1%9C-%EB%B0%94%EA%BE%B8%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n    - [깃 풀 받을때 로컬 파일을 덮어씌우고 싶어](#%EA%B9%83-%ED%92%80-%EB%B0%9B%EC%9D%84%EB%95%8C-%EB%A1%9C%EC%BB%AC-%ED%8C%8C%EC%9D%BC%EC%9D%84-%EB%8D%AE%EC%96%B4%EC%94%8C%EC%9A%B0%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n    - [파일을 로컬에는 보관하고 깃에서 지우고 싶어](#%ED%8C%8C%EC%9D%BC%EC%9D%84-%EB%A1%9C%EC%BB%AC%EC%97%90%EB%8A%94-%EB%B3%B4%EA%B4%80%ED%95%98%EA%B3%A0-%EA%B9%83%EC%97%90%EC%84%9C-%EC%A7%80%EC%9A%B0%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n    - [특정한 버전대로 파일을 복구하고 싶어](#%ED%8A%B9%EC%A0%95%ED%95%9C-%EB%B2%84%EC%A0%84%EB%8C%80%EB%A1%9C-%ED%8C%8C%EC%9D%BC%EC%9D%84-%EB%B3%B5%EA%B5%AC%ED%95%98%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n    - [커밋과 브랜치 간의 특정 파일 변경 이력이 필요해](#%EC%BB%A4%EB%B0%8B%EA%B3%BC-%EB%B8%8C%EB%9E%9C%EC%B9%98-%EA%B0%84%EC%9D%98-%ED%8A%B9%EC%A0%95-%ED%8C%8C%EC%9D%BC-%EB%B3%80%EA%B2%BD-%EC%9D%B4%EB%A0%A5%EC%9D%B4-%ED%95%84%EC%9A%94%ED%95%B4)\n  - [설정](#%EC%84%A4%EC%A0%95)\n    - [깃 명령어 몇 개를 앨리어스 등록하고 싶어](#%EA%B9%83-%EB%AA%85%EB%A0%B9%EC%96%B4-%EB%AA%87-%EA%B0%9C%EB%A5%BC-%EC%95%A8%EB%A6%AC%EC%96%B4%EC%8A%A4-%EB%93%B1%EB%A1%9D%ED%95%98%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n    - [레파지토리에 빈 디렉토리를 추가하고 싶어](#%EB%A0%88%ED%8C%8C%EC%A7%80%ED%86%A0%EB%A6%AC%EC%97%90-%EB%B9%88-%EB%94%94%EB%A0%89%ED%86%A0%EB%A6%AC%EB%A5%BC-%EC%B6%94%EA%B0%80%ED%95%98%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n    - [레파지토리 유저명과 비밀번호를 캐시해두고 싶어](#%EB%A0%88%ED%8C%8C%EC%A7%80%ED%86%A0%EB%A6%AC-%EC%9C%A0%EC%A0%80%EB%AA%85%EA%B3%BC-%EB%B9%84%EB%B0%80%EB%B2%88%ED%98%B8%EB%A5%BC-%EC%BA%90%EC%8B%9C%ED%95%B4%EB%91%90%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n    - [깃이 권한과 파일모드 변경을 무시하게 만들고 싶어](#%EA%B9%83%EC%9D%B4-%EA%B6%8C%ED%95%9C%EA%B3%BC-%ED%8C%8C%EC%9D%BC%EB%AA%A8%EB%93%9C-%EB%B3%80%EA%B2%BD%EC%9D%84-%EB%AC%B4%EC%8B%9C%ED%95%98%EA%B2%8C-%EB%A7%8C%EB%93%A4%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n    - [글로벌 유저로 설정해두고 싶어](#%EA%B8%80%EB%A1%9C%EB%B2%8C-%EC%9C%A0%EC%A0%80%EB%A1%9C-%EC%84%A4%EC%A0%95%ED%95%B4%EB%91%90%EA%B3%A0-%EC%8B%B6%EC%96%B4)\n  - [뭘 잘못했는지 모르겠어](#%EB%AD%98-%EC%9E%98%EB%AA%BB%ED%96%88%EB%8A%94%EC%A7%80-%EB%AA%A8%EB%A5%B4%EA%B2%A0%EC%96%B4)\n- [다른 리소스](#%EB%8B%A4%EB%A5%B8-%EB%A6%AC%EC%86%8C%EC%8A%A4)\n  - [도서](#%EB%8F%84%EC%84%9C)\n  - [튜토리얼](#%ED%8A%9C%ED%86%A0%EB%A6%AC%EC%96%BC)\n  - [스크립트와 도구](#%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%99%80-%EB%8F%84%EA%B5%AC)\n  - [GUI 클라이언트](#gui-%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n## 레파지토리\n\n### 로컬 레파지토리에서 시작하고 싶어\n\n이미 존재하는 프로젝트 디렉토리를 깃 레파지토리로 최적화해 쓰려면:\n\n```sh\n(my-folder) $ git init\n```\n\n### 난 리모트 레파지토리를 복제해오고 싶어\n\n리모트 레파지토리를 클론하려면, 레파지토리 URL을 복사해와서 실행해요.\n\n```sh\n$ git clone [url]\n```\n\n폴더 이름이 리모트 레파지토리 이름과 같이 저장될 거에요.\n\n복제할 리모트 서버의 연결을 확인하세요.(대부분 인터넷 연결을 확인하란 뜻이에요)\n\n다른 레파지토리 이름으로 복제를 해오고 싶다면\n\n```sh\n$ git clone [url] name-of-new-folder\n```\n\n## 커밋 수정\n\n<a name=\"diff-last\"></a>\n<!-- ### What did I just commit? -->\n### 내가 방금 어떤 커밋을 남겼지?\n\n`git commit -a` 로 막 커밋을 남기고 내가 뭐라고 안에 적었더라? 한다고 하고. 최근의 커밋을 현재 HEAD에서 볼 수 있어요.\n\n```sh\n(main)$ git show\n```\n\n또는\n\n```sh\n$ git log -n1 -p\n```\n\n만약 특정 커밋의 파일을 보고 싶다면, 이렇게 할 수도 있어요. (commitID는 바로 당신이 관심있는 그 commit이에요)\n\n```sh\n$ git show <commitid>:filename\n```\n\n<a name=\"wrong-thing-in-commit-message\"></a>\n### 커밋 메세지를 잘못 썼어\n\n만약 메시지를 잘못 썼고 아직 푸시를 안했다면, 커밋 메시지 바꾸기를 따라해 볼 수 있어요.\n\n```sh\n$ git commit --amend --only\n```\n\n이 방법은 편집 가능한 기본 텍스트 에디터가 열릴텐데요, 다른 방법으론 한줄에 쓸 수도 있어요.\n\n```sh\n$ git commit --amend --only -m 'xxxxxxx'\n```\n\n만약 푸시를 이미 했다면, 커밋을 수정해서 강제 푸시를 할 수 있긴한대 별로 추천하진 않아요.\n\n<a name=\"commit-wrong-author\"></a>\n### 커밋을 다른 이름과 이메일 설정으로 해버렸어\n\n하나의 커밋이라면 이렇게 수정해요.\n\n```sh\n$ git commit --amend --no-edit --author \"New Authorname <authoremail@mydomain.com>\"\n```\n\n대안으로는 `git config --global author.(name|email)`에서 설정을 다시 맞춘 다음\n\n```sh\n$ git commit --amend --reset-author --no-edit\n```\n\n만약 전체 이력 변경이 필요하다면, `git filter-branch`의 설명 페이지를 봐요.\n\n### 지난 커밋에서 파일 하나를 지우고 싶어\n\n지난 커밋에서 파일 변경내역을 지우려면, 이렇게 해봐요:\n\n```sh\n$ git checkout HEAD^ myfile\n$ git add myfile\n$ git commit --amend --no-edit\n```\n\n그 파일이 새롭게 커밋으로 추가됐고 그 파일만 지우고 (git 에서만) 싶은 경우엔,\n\n```sh\n$ git rm --cached myfile\n$ git commit --amend --no-edit\n```\n\n이 방법은 열린 패치가 있고 불필요한 파일을 커밋 했거나 리모트에 강제 푸시로 패치를 업데이트 해야할때 특히 유용해요. `--no-edit` 옵션은 기존 커밋 메세지를 유지하는데 사용돼요.\n\n<a name=\"delete-pushed-commit\"></a>\n### 마지막 커밋을 지우고 싶어\n\n푸시된 커밋을 지우고 싶다면 이걸 따라하면 되는데, 이력을 돌이킬 수 없게 되고 레파지토리에서 이미 풀을 받아간 다른 사람의 이력도 엉망이 되요. 간단히 말하자면, 잘 모르겠으면 절대 하지마요.\n\n```sh\n$ git reset HEAD^ --hard\n$ git push --force-with-lease [remote] [branch]\n```\n\n아직 푸시 안했으면, 리셋으로 마지막 커밋 전 상태로 돌아가요. (변경점은 스테이지에 두고서)\n\n```\n(my-branch)$ git reset --soft HEAD^\n```\n\n이 방법은 푸시를 안 했을 때만 동작해요. 푸시를 했으면, 안전한 방법은 `git revert SHAofBadCommit` 한가지 밖이에요.\n이 방법은 모든 지난 커밋 변경점으로 되돌아간 새 커밋을 만들 거에요. 또는, 만약 푸시한 브랜치가 리베이스에 안전하다면 (만약 다른 사람이 풀 받지 않는다면), `git push --force-with-lease` 명령어를 쓸수 있어요.\n더 알고 싶다면, [이 섹션](#deleteremove-last-pushed-commit)을 참고해주세요.\n\n<a name=\"delete-any-commit\"></a>\n### 임의적인 커밋 지우기\n\n이전과 동일한 경고에요. 가능한 이 방법은 쓰지 마세요.\n\n```sh\n$ git rebase --onto SHA1_OF_BAD_COMMIT^ SHA1_OF_BAD_COMMIT\n$ git push --force-with-lease [remote] [branch]\n```\n\n아니면 [대화형 리베이스](#interactive-rebase)를 쓰고 지우고 싶은 커밋 라인을 지워도 돼요.\n\n<a name=\"force-push\"></a>\n### 수정된 커밋을 푸시했는데, 에러 메세지가 떠\n\n```sh\nTo https://github.com/yourusername/repo.git\n! [rejected]        mybranch -> mybranch (non-fast-forward)\nerror: failed to push some refs to 'https://github.com/tanay1337/webmaker.org.git'\nhint: Updates were rejected because the tip of your current branch is behind\nhint: its remote counterpart. Integrate the remote changes (e.g.\nhint: 'git pull ...') before pushing again.\nhint: See the 'Note about fast-forwards' in 'git push --help' for details.\n```\n\n알아두세요, 리베이스(아래를 보세요)나 어멘드는 **기존 커밋을 새걸로 바꿔요**,\n그래서 이미 먼저 수정된 커밋이 푸시됐다면 강제 푸시를 해야 해요.\n이 방법을 쓸땐 조심하세요; *항상* 작업되는 브랜치가 맞나 확인해요!\n\n```sh\n(my-branch)$ git push origin mybranch --force-with-lease\n```\n\n일반적으로 강제 푸시를 쓰지 마세요.\n새 커밋을 만들어서 푸시하는게 수정된 커밋을 강제로 푸시하는 것보다 훨씬 나아요. 그런 수정된 커밋은 그 브랜치나 다른 자식 브랜치를 쓰는 다른 개발자의 소스 이력과 충돌의 원인이 될거에요.\n`--force-with-lease` 는 여전히 실패할텐데, 누군가가 같은 브랜치를 쓴다면 변경점을 덮어쓰는 푸시를 할 수도 있어요.\n\n절대로 아무도 같은 브랜치를 안 쓰거나, 절대로 브랜치에 업데이트를 해야할때 `--force` (`-f`) 옵션을 쓸 수 있지만 일반적으론 피하는게 좋아요.\n\n<a name=\"undo-git-reset-hard\"></a>\n### 하드 리셋을 해버렸는데 되돌리고 싶어\n\n만약 하드 리셋을 했다고 해도 커밋을 돌릴 순 있어요. 깃은 며칠간은 로그를 가지고 있거든요.\n\n알아두기 : 이건 커밋을 남겼거나 스테이시같이 백업을 했을 때만 유효해요. `git reset --hard` 은 커밋되지 않은 수정사항을 _다 지울 거에요_, 그러니 조심해서 써야해요. (안전한 방법으론 `git reset --keep` 이 있어요)\n\n```sh\n(main)$ git reflog\n```\n\n지난 커밋과 리셋을 위한 커밋을 볼 수 있을 거에요. 돌아가고 싶은 커밋의 SHA 코드를 골라서, 리셋을 해요:\n\n```sh\n(main)$ git reset --hard SHA1234\n```\n\n계속 할 수 있을거에요.\n\n<a name=\"undo-a-commit-merge\"></a>\n### 머지를 실수로 커밋, 푸시해버렸어\n\n만약 실수로 머지할 준비가 안된 피쳐 브랜치를 메인 브랜치에 머지했어도 되돌릴 순 있어요.\n하지만 문제는 있어요: 머지 커밋은 한개 이상의 부모(보통은 두 개)를 가지게 돼요.\n\n사용하려면\n\n```sh\n(feature-branch)$ git revert -m 1 <commit>\n```\n\n여기서 -m 1 옵션은 부모 번호 1(머지가 만들어진 브랜치)을 되돌릴 상위 항목으로 선택하라고 해요.\n\n알아두기 : 부모 번호는 커밋 식별자가 아니고, 오히려 머지된 커밋이 `Merge: 8e2ce2d 86ac2e7` 이라는 라인을 가지고 있어요.\n부모 번호는 이 라인에서 원하는 부모의 1 기반 인덱스이고, 첫번째 식별자는 1, 다음은 2 이렇게 이어져요.\n\n## 스테이지\n\n<a name=\"add-staged-changes-to-previous-commit\"></a>\n### 지난 커밋에 스테이지 변경점을 추가하고 싶어\n\n```sh\n(my-branch*)$ git commit --amend\n```\n\n<a name=\"commit-partial-new-file\"></a>\n### 전체가 아닌 새 파일만 스테이지에 올리고 싶어\n\n보통은 부분적으로 파일을 스테이지하려면 이렇게 해요:\n\n```sh\n$ git add --patch filename.x\n```\n\n`-p`는 축약된 옵션이에요. 이 방식은 대화형 모드를 열텐데요. `s` 옵션을 쓰면 커밋을 나눌 수 있어요. 하지만 새 파일이라면 그런 옵션이 없을거에요. 새 파일을 추가하려면:\n\n```sh\n$ git add -N filename.x\n```\n\n그 다음 임의적으로 라인들을 골라 추가해주려면 `e`옵션이 필요할거에요. `git diff --cached`나 `git diff --staged`는 로컬에 저장된 부분과 스테이지에 있는 라인들을 비교해서 보여줄 거에요.\n\n<a name=\"stage-in-two-commits\"></a>\n### 하나의 파일 변경점을 두개의 다른 커밋에 남기고 싶어\n\n`git add`는 전체 파일들을 커밋에 추가해요. `git add -p`는 대화형으로 추가하고픈 변경점들을 고를 수 있어요.\n\n<a name=\"unstaging-edits-and-staging-the-unstaged\"></a>\n### 아직 스테이지에 안 올라간 변경점을 스테이지에 추가하고, 스테이지에 있는 변경점을 다시 빼고 싶어\n\n이건 좀 꼼수인데요, 스테이지 전인 파일들을 스테이시해서 빼두고선 리셋 할 수 있을거에요. 그 다음 스테이시를 다시 불러와 추가를 해요.\n\n```sh\n$ git stash -k\n$ git reset --hard\n$ git stash pop\n$ git add -A\n```\n\n## 스테이지 전의 변경점\n\n<a name=\"move-unstaged-edits-to-new-branch\"></a>\n### 스테이지 전의 변경점을 새 브랜치로 옮기고 싶어\n\n```sh\n$ git checkout -b my-branch\n```\n\n<a name=\"move-unstaged-edits-to-old-branch\"></a>\n### 스테이지전 변경점을 만들어둔 다른 브랜치로 옮기고 싶어\n\n```sh\n$ git stash\n$ git checkout my-branch\n$ git stash pop\n```\n\n<a name=\"discard-local-uncommitted-changes\"></a>\n### 내 로컬에 있는 커밋 안된 변경점을 다 무시하고 싶어 (스테이징 됐던 안됐던)\n\n만약 모든 스테이징 됐거나 안 된 변경점을 버리고 싶다면 이렇게 해요:\n\n```sh\n(my-branch)$ git reset --hard\n# or\n(main)$ git checkout -f\n```\n\n이 방법은 `git add`로 스테이징된 모든 파일이 빠지게 돼요.\n\n```sh\n$ git reset\n```\n\n이 방법은 커밋되지 않은 모든 로컬 변경점이 되돌려 져요. (레파지토리 최상단 루트에서 실행해야 할거에요)\n\n```sh\n$ git checkout .\n```\n\n또 커밋되지 않은 변경점들 중 몇가지 파일이나 디렉토리만 되돌릴 수 있어요.\n\n```sh\n$ git checkout [some_dir|file.txt]\n```\n\n거기에 또 다른 되돌리는 방법으로 (타이핑 칠게 많지만 어떤 하위 디렉토리에서도 돼요):\n\n```sh\n$ git reset --hard HEAD\n```\n\n이 방법은 모든 트래킹되지 않은 파일들을 지워요, 그래서 깃에서 트래킹되는 파일들만 남아요:\n\n```sh\n$ git clean -fd\n```\n\n`-x` 옵 또한 무시된 파일들을 다 지워요.\n\n### 스테이지 안된 특정 변경점을 지우고 싶어\n\n작업중인 영역에서 전체가 아닌 특정 부분을 지우고 싶을때\n원치않는 변경점을 확인하고, 변경점을 잘 보관하세요.\n\n```sh\n$ git checkout -p\n# 날리고 싶은 사항에 y를 적으세요\n```\n\n또다른 전략은 `stash`을 같이 쓰는거에요. 챙겨야 하는 변경점을 스테이시 하고, 작업 중인 영역을 리셋하고, 다시 올바른 변경점으로 재적용해요.\n\n```sh\n$ git stash -p\n# 저장하고 싶은 사항들을 다 선택하세요\n$ git reset --hard\n$ git stash pop\n```\n\n대안으로, 원치않는 변경점을 스테이시해서 그걸 날리는 방법도 있어요.\n\n```sh\n$ git stash -p\n# 저장하고 싶지 앟은 사항들을 다 선택하세요\n$ git stash drop\n```\n\n### 스테이지 안된 특정 파일을 지우고 싶어\n\n작업 영역에서 특정 파일을 지우고 싶을 때.\n\n```sh\n$ git checkout myFile\n```\n\n대안으로, 작업영역 내 여러 파일들을 지우고 싶을때 모두 나열해서 적어요.\n\n```sh\n$ git checkout myFirstFile mySecondFile\n```\n\n### 로컬에 있는 스테이지 안된 변경점만 지우고 싶어\n\n모든 스테이징 안된 커밋 전인 변경점을 지우고 싶을 때\n\n```sh\n$ git checkout .\n```\n\n<a name=\"discard-all-untracked-files\"></a>\n### 트래킹 안된 파일들 다 지우고 싶어\n\n트래킹 안된 파일들 다 지우고 싶을 땐\n\n```sh\n$ git clean -f\n```\n\n## 브랜치\n\n### 모든 브랜치 리스트를 보고 싶어\n\n로컬 브랜치 다 보기\n\n```sh\n$ git branch\n```\n\n리모트 브랜치 다 보기\n\n```sh\n$ git branch -r\n```\n\n로컬과 리모트 브랜치 모두 보기\n\n```sh\n$ git branch -a\n```\n\n<a name=\"create-branch-from-commit\"></a>\n### 커밋에서 브랜치 만들기\n\n```sh\n$ git checkout -b <branch> <SHA1_OF_COMMIT>\n```\n\n<a name=\"pull-wrong-branch\"></a>\n### 다른 브랜치에서 풀을 받아와버렸어\n\n이건 잘못된 풀을 받기전 HEAD가 어딜 가르키고 있었는지 볼 수 있는 `git reflog`를 써볼 수 있는 기회에요.\n\n```sh\n(main)$ git reflog\nab7555f HEAD@{0}: pull origin wrong-branch: Fast-forward\nc5bc55a HEAD@{1}: checkout: checkout message goes here\n```\n\n간단히 원하는 커밋으로 브랜치를 되돌릴 수 있어요:\n\n```sh\n$ git reset --hard c5bc55a\n```\n\n끝!\n\n<a name=\"discard-local-commits\"></a>\n### 로컬의 커밋을 지워서 서버에 있는 내 브랜치와 맞추고 싶어\n\n서버에 변경점을 푸시 안했는지부터 확인해요.\n\n`git status` 가 오리진보다 몇개의 커밋들이 앞서 있는지 보여줄거에요:\n\n```sh\n(my-branch)$ git status\n# On branch my-branch\n# Your branch is ahead of 'origin/my-branch' by 2 commits.\n#   (use \"git push\" to publish your local commits)\n#\n```\n\n오리진(리모트과 같은 상태의)로 맞추는 리셋을 하는 방법 중 하나는:\n\n```sh\n(my-branch)$ git reset --hard origin/my-branch\n```\n\n<a name=\"commit-wrong-branch\"></a>\n### 새 브랜치 대신에 마스터에 커밋을 해버렸어\n\n마스터에 있으면서 새 브랜치를 만들어요:\n\n```sh\n(main)$ git branch my-branch\n```\n\n마스터 브랜치를 기존 커밋으로 리셋해요:\n\n\n```sh\n(main)$ git reset --hard HEAD^\n```\n\n`HEAD^`는 `HEAD^1`의 축약인데요. `HEAD^`의 첫번째 부모를 의미하고, 비슷한 `HEAD^2`는 두번째 부모를 의미해요. (머지는 두 부모를 가질 수 있죠)\n\n알아두세요 `HEAD^2`는 `HEAD~2`과 같은게 아니에요. (더 자세한 정보는 [이 링크](http://www.paulboxley.com/blog/2011/06/git-caret-and-tilde)를 참고해요 )\n\n대안으로, `HEAD^`를 쓰고 싶지 않다면, 마스터 브랜치로 옮길 커밋 해시를 알아둬요 (`git log`가 트릭을 부릴 거에요) 그리고 그 해쉬로 리셋을 해요. `git push`가 리모트랑 변경점이 똑같은걸 확인해줄거에요.\n\n예를 들자면, 그 마스터의 커밋의 해쉬가 `a13b85e`라면:\n\n```sh\n(main)$ git reset --hard a13b85e\nHEAD is now at a13b85e\n```\n\n새 브랜치로 체크아웃 해서 계속 작업을 해요:\n\n```sh\n(main)$ git checkout my-branch\n```\n\n<a name=\"keep-whole-file\"></a>\n### 다른 레퍼런스 같은 곳에서 모든 파일을 유지하고 싶어\n\n수백번의 변경점을 가진 스파이크(아래 알아두기 참고) 작업을 한다고 가정해보죠. 모든 건 동작하고 있고,그 작업을 저장해두기 위해  다른 브랜치로 커밋을 해요:\n\n```sh\n(solution)$ git add -A && git commit -m \"Adding all changes from this spike into one big commit.\"\n```\n\n그 커밋을 브랜치(아마 feature일수도 있고, `develop` 일수도 있겠죠)에 넣고 싶을 때, 모든 파일을 지키는데 관심이 있을거에요. 큰 커밋을 작게 나누고 싶을거에요.\n\n현재 가지고 있는건:\n\n* 스파이크를 위한 솔루션과 함께인 `solution` 브랜치. `develop` 브랜치의 1단계 앞선 상태.\n* 변경점을 추가하고 싶은 `develop` 브랜치\n\n브랜치로 내용들을 불러오는 것으로 해결할 수 있어요:\n\n```sh\n(develop)$ git checkout solution -- file1.txt\n```\n\n`develop`브랜치에서 `solution` 브랜치의 저 파일의 내용들을 얻을 수 있어요.\n\n```sh\n# On branch develop\n# Your branch is up-to-date with 'origin/develop'.\n# Changes to be committed:\n#  (use \"git reset HEAD <file>...\" to unstage)\n#\n#        modified:   file1.txt\n```\n\n그 다음, 평소처럼 커밋해요.\n\n알아두기 : 스파이크 솔루션은 문제를 분석하거나 풀기위해 만들어졌어요. 이 솔루션들은 모두가 문제의 확실한 시각화를 얻고선 평가되고 제거돼요.~ [위키피디아](https://en.wikipedia.org/wiki/Extreme_programming_practices).\n\n<a name=\"cherry-pick\"></a>\n### 한 브랜치에 다른 브랜치에 남겼어야 하는 커밋을 여러개 남겼어\n\n마스터 브랜치에 있다고 가정하고 `git log` 해보면 커밋 두개 볼 수 있을거에요:\n\n```sh\n(main)$ git log\n\ncommit e3851e817c451cc36f2e6f3049db528415e3c114\nAuthor: Alex Lee <alexlee@example.com>\nDate:   Tue Jul 22 15:39:27 2014 -0400\n\n    Bug #21 - Added CSRF protection\n\ncommit 5ea51731d150f7ddc4a365437931cd8be3bf3131\nAuthor: Alex Lee <alexlee@example.com>\nDate:   Tue Jul 22 15:39:12 2014 -0400\n\n    Bug #14 - Fixed spacing on title\n\ncommit a13b85e984171c6e2a1729bb061994525f626d14\nAuthor: Aki Rose <akirose@example.com>\nDate:   Tue Jul 21 01:12:48 2014 -0400\n\n    First commit\n```\n\n각 버그커밋의 해쉬를 가져와요. (21번은 `e3851e8`, 14번은 `5ea5173`)\n\n우선, 마스터 브랜치의 정확한 커밋 (`a13b85e`)으로 리셋해요:\n\n```sh\n(main)$ git reset --hard a13b85e\nHEAD is now at a13b85e\n```\n\n그리고, 21번 버그 작업을 위한 새로운 브랜치를 만들수 있어요:\n\n```sh\n(main)$ git checkout -b 21\n(21)$\n```\n\n그리고 21번 버그 커밋을 *체리픽* 해서 브랜치 최상단에 올려요. 그 커밋을 적용할건데, 오직 그 커밋만을 헤드에 뭐가 있든 최상단으로 적용할거란 의미에요.\n\n```sh\n(21)$ git cherry-pick e3851e8\n```\n\n이 지점에서 충돌이 있을 수도 있어요.\n어떻게 충돌을 해결할지 [대화형 리베이스 섹션](#interactive-rebase) 안에 있는 [**충돌이 있어**](#merge-conflict) 부분을 참고하세요.\n\n자 이제 14번 버그 작업을 위해 마스터로 가서 새 브랜치를 만들어요.\n\n```sh\n(21)$ git checkout main\n(main)$ git checkout -b 14\n(14)$\n```\n\n그리고 마지막으로, 14번 버그작업을 위한 커밋을 체리픽해요.\n\n```sh\n(14)$ git cherry-pick 5ea5173\n```\n\n<a name=\"delete-stale-local-branches\"></a>\n### 업스트림에선 지워진 로컬 브랜치를 지우고 싶어\n\n깃헙에 풀리퀘스트로 머지를 하면, 포크 뜬 머지 브랜치를 지울껀지 선택할 수 있는 옵션을 줘요.\n해당 브랜치에 계속 작업할 예정이 없다면, 다량의 오래된 브랜치들로 뒤덮이지 않게 로컬 작업을 지워주는게 더 깔끔해요.\n\n```sh\n$ git fetch -p upstream\n```\n\n여기서, `upstream`은 패치로 가져오려는 리모트 레파지토리에요.\n\n<a name=\"restore-a-deleted-branch\"></a>\n### 브랜치를 지워버렸어\n\n주기적으로 리모트으로 푸시한다면, 대부분은 안전해야 해요. 그치만 가끔은 브랜치를 지울 수 있어요. 새 브랜치를 만들고 파일을 하나 만들었다고 해보죠:\n\n```sh\n(main)$ git checkout -b my-branch\n(my-branch)$ git branch\n(my-branch)$ touch foo.txt\n(my-branch)$ ls\nREADME.md foo.txt\n```\n\n추가하고 커밋해요.\n\n```sh\n(my-branch)$ git add .\n(my-branch)$ git commit -m 'foo.txt added'\n(my-branch)$ foo.txt added\n 1 files changed, 1 insertions(+)\n create mode 100644 foo.txt\n(my-branch)$ git log\n\ncommit 4e3cd85a670ced7cc17a2b5d8d3d809ac88d5012\nAuthor: siemiatj <siemiatj@example.com>\nDate:   Wed Jul 30 00:34:10 2014 +0200\n\n    foo.txt added\n\ncommit 69204cdf0acbab201619d95ad8295928e7f411d5\nAuthor: Kate Hudson <katehudson@example.com>\nDate:   Tue Jul 29 13:14:46 2014 -0400\n\n    Fixes #6: Force pushing after amending commits\n```\n\n이제 다시 마스터로 돌아가 '실수로' 브랜치를 지워보죠.\n\n```sh\n(my-branch)$ git checkout main\nSwitched to branch 'main'\nYour branch is up-to-date with 'origin/main'.\n(main)$ git branch -D my-branch\nDeleted branch my-branch (was 4e3cd85).\n(main)$ echo oh noes, deleted my branch!\noh noes, deleted my branch!\n```\n\n여기에서 업그레이드된 로그 도구인 '리플로그'에 익숙해져야 해요. 리플로그는 레파지토리의 모든 행동의 이력을 다 보관해요.\n\n```\n(main)$ git reflog\n69204cd HEAD@{0}: checkout: moving from my-branch to main\n4e3cd85 HEAD@{1}: commit: foo.txt added\n69204cd HEAD@{2}: checkout: moving from main to my-branch\n```\n\n보시다시피 지워진 브랜치의 커밋 해쉬도 볼 수 있어요. 지웠던 브랜치를 살릴 수 있는 지 한번 해보죠.\n\n```sh\n(main)$ git checkout -b my-branch-help\nSwitched to a new branch 'my-branch-help'\n(my-branch-help)$ git reset --hard 4e3cd85\nHEAD is now at 4e3cd85 foo.txt added\n(my-branch-help)$ ls\nREADME.md foo.txt\n```\n\n짜잔! 지워진 파일들을 되돌려 놨어요. `git reflog`는 리베이스가 끔찍하게 잘못 됐을때 아주 유용해요.\n\n### 브랜치를 지우고 싶어\n\n리모트 브랜치를 삭제하려면:\n\n```sh\n(main)$ git push origin --delete my-branch\n```\n\n이렇게도:\n\n```sh\n(main)$ git push origin :my-branch\n```\n\n로컬 브랜치를 삭제하려면:\n\n```sh\n(main)$ git branch -d my-branch\n```\n\n현재 브랜치나 업스트림에 머지되지 않은 로컬 브랜치를 지우려면:\n\n```sh\n(main)$ git branch -D my-branch\n```\n\n### 여러개의 브랜치를 지우고 싶어\n\n`fix/`로 시작하는 모든 브랜치들을 지우고 싶다면:\n\n```sh\n(main)$ git branch | grep 'fix/' | xargs git branch -d\n```\n\n### 브랜치 이름을 바꾸고 싶어\n\n현재 (로컬) 브랜치 이름을 바꾸려면:\n\n```sh\n(main)$ git branch -m new-name\n```\n\n다른 (로컬) 브랜치 이름을 바꾸려면\n\n```sh\n(main)$ git branch -m old-name new-name\n```\n\n<a name=\"working-on-checkout-remote-branch\"></a>\n### 다른 사람이 작업중인 리모트 브랜치로 체크아웃 하고 싶어\n\n우선, 리모트 레파지토리에서 모든 브랜치를 패치 받아요:\n\n```sh\n(main)$ git fetch --all\n```\n\n리모트의 `daves`로 체크아웃 하고 싶다고 하면.\n\n```sh\n(main)$ git checkout --track origin/daves\nBranch daves set up to track remote branch daves from origin.\nSwitched to a new branch 'daves'\n```\n\n(`--track` 은 `git checkout -b [branch] [remotename]/[branch]` 의 축약이에요)\n\n`daves` 브랜치의 로컬 카피를 줄거에요. 그리고 푸시된 업데이트들도 리모트로 표시돼요.\n\n### 현재 로컬 브랜치로 새로운 리모트 브랜치를 만들고 싶어\n\n```sh\n$ git push <remote> HEAD\n```\n\n또한 리모트 브랜치를 현재 브랜치를 위한 업스트림으로 설정하고 싶다면, 대신 아래 방법을 써봐요:\n\n```sh\n$ git push -u <remote> HEAD\n```\n\n`push.default` 설정의 `upstream` 모드와 `simple`모드 (2.0 버전의 깃의 기본)와 함께,\n아래 커맨드는 이전에 `-u` 옵션으로 등록된 리모트 브랜치와 관련된 현재 브랜치를 푸시할거에요:\n\n```sh\n$ git push\n```\n\n`git push`의 다른 모드의 동작은 [`push.default` 문서](https://git-scm.com/docs/git-config#Documentation/git-config.txt-pushdefault)에 설명돼 있어요.\n\n### 리모트 브랜치를 로컬 브랜치를 위한 업스트림으로 설정하고 싶어\n\n리모트 브랜치를 현재 쓰고 있는 로컬 브랜치를 위한 업스트림으로 설정할 수 있어요:\n\n```sh\n$ git branch --set-upstream-to [remotename]/[branch]\n# 아니면 짧게:\n$ git branch -u [remotename]/[branch]\n```\n\n다른 로컬 브랜치를 위한 업스트림 리모트 브랜치를 설정하려면:\n\n```sh\n$ git branch -u [remotename]/[branch] [local-branch]\n```\n\n<a name=\"head-to-track-remote-branch\"></a>\n### HEAD를 기본 리모트 브랜치로 트래킹하도록 설정하고 싶어\n\n리모트 브랜치를 확인해보는 것으로, HEAD가 트래킹 중인 리모트 브랜치를 볼 수 있어요. 몇몇 경우에는, 원하던 브랜치가 아닐거에요.\n\n```sh\n$ git branch -r\n  origin/HEAD -> origin/gh-pages\n  origin/main\n```\n\n`origin/HEAD`를 `origin/main`를 트래킹하는 것으로 변경하려면, 이 커맨드로 실행할 수 있어요:\n\n```sh\n$ git remote set-head origin --auto\norigin/HEAD set to main\n```\n\n### 다른 브랜치에 변경점을 잘못 남겼어\n\n커밋 되지 않은 변경점, 거기다 잘못된 브랜치에 하고 있었다면 변경점을 스테이시 하고 원하는 브랜치로 가 스테이시 어플라이 해요:\n\n```sh\n(wrong_branch)$ git stash\n(wrong_branch)$ git checkout <correct_branch>\n(correct_branch)$ git stash apply\n```\n\n## 리베이스와 머지\n\n<a name=\"undo-rebase\"></a>\n### 리베이스/머지 한 걸 되돌리고 싶어\n\n현재 브랜치를 의도하지 않던 브랜치로 머지 또는 리베이스 했거나, 리베이스/머지 도중에 완료하거나 끝내지 못했을거에요.\n깃은 위험한 과정 전에 원래의 HEAD 포인트를 ORIG_HEAD라 불리는 변수에 보관해요, 그러니 리베이스/머지 전 상태로 브랜치를 복구하기 간단해요.\n\n```sh\n(my-branch)$ git reset --hard ORIG_HEAD\n```\n\n<a name=\"force-push-rebase\"></a>\n### 리베이스를 했는데, 강제 푸시하고 싶진 않아\n\n아쉽게도 그런 변경점을 리모트 브랜치에 반영하려면 강제 푸시밖에 방법이 없어요. 이력을 변경해왔기 때문이죠.\n리모트 브랜치는 강제 푸시 외엔 적용 해주지 않을거에요.\n많은 분들이 머지 워크플로우를 리베이스 워크플로우보다 선호하는 많이 이유 중 하나죠 - 큰 팀에선 개발자의 강제 푸시로 곤란해질 수 있어요.\n주의해서 쓰세요.\n리베이스를 그나마 안전하게 쓰는 방법은 리모트 브랜치의 모든 변경점과 똑같이 반영하는게 아니라 대신에 이렇게 해봐요:\n\n\n```sh\n(main)$ git checkout my-branch\n(my-branch)$ git rebase -i main\n(my-branch)$ git checkout main\n(main)$ git merge --ff-only my-branch\n```\n\n더 확인이 필요하다면, [이 스택오버플로우의 쓰레드](https://stackoverflow.com/questions/11058312/how-can-i-use-git-rebase-without-requiring-a-forced-push)를 참고해요.\n\n\n<a name=\"interactive-rebase\"></a>\n### 커밋끼리 합치고 싶어\n\n`main`에 풀 리퀘스트가 될 브랜치에서 작업하고 있다고 가정해봐요.\n가장 간단한 경우는 원하는게 *모든* 커밋을 하나의 커밋으로 합치고 변경점의 시간을 신경쓰지 않아도 되는 것일 때, 리셋하고 커밋 다시하면 돼요.\n마스터 브랜치가 최신이고 모든 변경점이 커밋된 것만 확인한 다음:\n\n```sh\n(my-branch)$ git reset --soft main\n(my-branch)$ git commit -am \"New awesome feature\"\n```\n\n좀더 조정하고, 시간기록까지 보관하고 싶다면, 대화형 리베이스가 필요할거에요.\n\n```sh\n(my-branch)$ git rebase -i main\n```\n\n만약 다른 브랜치로 붙는 작업을 하는게 아니라면, `HEAD`을 기준으로 리베이스 해야해요.\n예로 마지막 2개의 커밋을 스쿼시(기존 커밋에 반영해넣는)하고 싶다면 `HEAD~2`로 리베이스 해요. 3개라면 `HEAD~3`으로 하구요.\n\n```sh\n(main)$ git rebase -i HEAD~2\n```\n\n대화형 리베이스를 실행하면 텍스트 에디터로 이런 것들을 볼 수 있을거에요.\n\n```vim\npick a9c8a1d Some refactoring\npick 01b2fd8 New awesome feature\npick b729ad5 fixup\npick e3851e8 another fix\n\n# Rebase 8074d12..b729ad5 onto 8074d12\n#\n# Commands:\n#  p, pick = use commit\n#  r, reword = use commit, but edit the commit message\n#  e, edit = use commit, but stop for amending\n#  s, squash = use commit, but meld into previous commit\n#  f, fixup = like \"squash\", but discard this commit's log message\n#  x, exec = run command (the rest of the line) using shell\n#\n# These lines can be re-ordered; they are executed from top to bottom.\n#\n# If you remove a line here THAT COMMIT WILL BE LOST.\n#\n# However, if you remove everything, the rebase will be aborted.\n#\n# Note that empty commits are commented out\n```\n\n모든 `#`으로 시작하는 주석줄은 리베이스에 영향을 주진 않아요.\n\n다음으로 `pick` 부분을 다른 명령어로 바꾸거나, 해당하는 라인을 지워서 커밋을 지울 수도 있어요.\n\n예를 들자면 **오래된 (첫번째) 커밋만 두고 두번째 오래된 커밋과 나머지를 다 합치고 싶을때**, 첫번째와 두번째 커밋 제외한 나머지 커맨드들을 `f`로 바꿔야 할거에요:\n\n```vim\npick a9c8a1d Some refactoring\npick 01b2fd8 New awesome feature\nf b729ad5 fixup\nf e3851e8 another fix\n```\n\n이 커밋들을 합치고 **커밋 이름을 바꾸고 싶다면**, 추가로 적어줘야 해요 두번째 커밋 다음에 `r`를 추가하거나 간단히 `f` 대신 `s`를 추가해주면 될거에요:\n\n```vim\npick a9c8a1d Some refactoring\npick 01b2fd8 New awesome feature\ns b729ad5 fixup\ns e3851e8 another fix\n```\n\n그런 다음에 한번 더 뜨는 텍스트 에디터로 커밋 이름을 바꿀 수 있어요.\n\n```vim\nNewer, awesomer features\n\n# Please enter the commit message for your changes. Lines starting\n# with '#' will be ignored, and an empty message aborts the commit.\n# rebase in progress; onto 8074d12\n# You are currently editing a commit while rebasing branch 'main' on '8074d12'.\n#\n# Changes to be committed:\n#   modified:   README.md\n#\n```\n\n전부 다 성공하면, 이런 메세지를 볼거에요:\n\n```sh\n(main)$ Successfully rebased and updated refs/heads/main.\n```\n\n#### 안전한 머지 전략\n\n`--no-commit`는 머지는 하지만 실패하고 자동 커밋이 안된것처럼 보이는데, 커밋하기전에 머지 결과를 보고 추가로 조정할 수 있게 해줘요.\n`no-ff`는 피쳐 브랜치가 있었다는 증거를 남기고, 이력을 일관되게 가지게 해요.\n\n\n```sh\n(main)$ git merge --no-ff --no-commit my-branch\n```\n\n#### 브랜치를 커밋 하나로 머지해야해\n\n```sh\n(main)$ git merge --squash my-branch\n```\n\n<a name=\"rebase-unpushed-commits\"></a>\n#### 푸시 되지 않은 커밋만 합치고 싶어\n\n가끔 여러가지 작업 도중인 커밋을 푸시하기 전에 합치고 싶을거에요.\n다른 누군가가 벌써 참고해서 커밋을 만들고 있을테니 이미 푸시된 커밋을 잘못 합치길 바라진 않을거에요.\n\n```sh\n(main)$ git rebase -i @{u}\n```\n\n이 명령은 아직 푸시하지 않은 커밋만으로 대화형 리베이스를 실행해요. 그러니 목록 내에 있는 어떤 커밋이든 재정렬/수정/합치기 안전해요.\n\n#### 머지를 중단해야해\n\n때때로 머지는 어떤 파일에 문제를 일으킬 수도 있어요, 이 경우 옵션 `abort`으로 현재 충돌 해결 프로세스를 중단하고 병합하기 전 상태로 다시 구성할 수 있어요.\n\n```sh\n(my-branch)$ git merge --abort\n```\n\n이 명령은 1.7.4 버전부터 쓸 수 있어요.\n\n### 브랜치내 모든 커밋이 머지됐는지 확인해\n\n브랜치 내 모든 커밋이 다른 브랜치로 머지됐는지 확인하려면, 그 브랜치들 HEAD (또는 특정 커밋)를 비교해야해요:\n\n```sh\n(main)$ git log --graph --left-right --cherry-pick --oneline HEAD...feature/120-on-scroll\n```\n\n이 명령은 어디에는 있고 다른덴 없는 커밋이 있나를 알려줄거에요 그리고 브랜치들 사이에 공유되지 않은게 목록을 보여줄 거구요. 다른 옵션은 이렇게:\n\n```sh\n(main)$ git log main ^feature/120-on-scroll --no-merges\n```\n\n### 대화형 리베이스로 발생가능한 이슈\n\n<a name=\"noop\"></a>\n#### 리베이스 편집 화면에서 'noop'\n\n이런 걸 본다면:\n\n```\nnoop\n```\n\n동일한 커밋에 있거나 현재 브랜치보다 앞서 있는 브랜치에 대해 리베이스를 시도한다는 의미에요. 이렇게 해볼 수 있어요:\n\n* 마스터 브랜치가 있어야 할 곳에 있나 확인\n* 대신해서 `HEAD~2` 또는 더 기존 항목을 리베이스\n\n<a name=\"merge-conflict\"></a>\n#### 충돌이 있어\n\n리베이스를 똑바로 끝내지 못했다면, 충돌을 해결해야 할거에요.\n\n어떤 파일이 충돌났는지 `git status`를 먼저 실행해봐요:\n\n```sh\n(my-branch)$ git status\nOn branch my-branch\nChanges not staged for commit:\n  (use \"git add <file>...\" to update what will be committed)\n  (use \"git checkout -- <file>...\" to discard changes in working directory)\n\n  both modified:   README.md\n```\n\n이 예시에선, `README.md` 가 충돌났네요. 파일을 열어서 아래와 같은 부분을 찾아봐요:\n\n```vim\n   <<<<<<< HEAD\n   some code\n   =========\n   some code\n   >>>>>>> new-commit\n```\n\n새로운 커밋으로 추가된 코드(예시에선, 중간 선부터 `new-commit` 까지의)와 `HEAD` 사이에서 차이점을 해결해야 할거에요.\n\n어느 한쪽 브랜치의 코드를 남기고 싶다면, `--ours` 또는 `--theirs`를 쓰면 돼요:\n\n```sh\n(main*)$ git checkout --ours README.md\n```\n\n- *머지*할때, `--ours`를 쓰면 로컬 브랜치의 변경점 유지하고, `--theirs` 는 다른 브랜치의 변경점를 유지해요.\n- *리베이스*할 땐, `--theirs`가 로컬 브랜치의 변경점을 유지하고 `--ours`는 다른 브랜치의 변경점을 유지해요. 이런 차이에 관한 설명은 Git 정식 문서 중 [이 문서](https://git-scm.com/docs/git-rebase#Documentation/git-rebase.txt---merge)를 보세요.\n\n만약 머지가 더 복잡하면, 비주얼 디프 에디터를 쓸 수도 있어요:\n\n```sh\n(main*)$ git mergetool -t opendiff\n```\n\n코드의 충돌을 해결하고 테스트가 해결되고 나면, 바뀐 파일 내용을 `git add` 해주고, `git rebase --continue`로 리베이스를 이어서 해요.\n\n```sh\n(my-branch)$ git add README.md\n(my-branch)$ git rebase --continue\n```\n\n만약 모든 충돌을 개선한 내용이 커밋 전과 동일한 트리 구조를 가진다면, 대신에 `git rebase --skip`를 해야 해요.\n\n리베이스 중 멈추고 싶은 어떤 시점이거나 원래 상태의 브랜치로 돌아가고 싶다면, 이렇게 할 수 있어요:\n\n```sh\n(my-branch)$ git rebase --abort\n```\n\n<a name=\"stashing\"></a>\n## 스테이시\n\n### 모든 변경점 스테이시 하기\n\n작업중인 디렉토리에서의 변경한 내용 전부를 스테이시 하려면\n\n```sh\n$ git stash\n```\n\n트래킹 되지 않은 파일까지도 포함하려면, `-u` 옵션을 써요.\n\n```sh\n$ git stash -u\n```\n\n### 특정 파일들만 스테이시 하기\n\n작업중인 디렉토리에서 한 파일만 스테이시 하기\n\n```sh\n$ git stash push working-directory-path/filename.ext\n```\n\n작업중인 디렉토리에서 여러 파일 스테이시 하기\n\n```sh\n$ git stash push working-directory-path/filename1.ext working-directory-path/filename2.ext\n```\n\n<a name=\"stash-msg\"></a>\n### 메세지와 함께 스테이시 하기\n\n```sh\n$ git stash save <message>\n```\n\n<a name=\"stash-apply-specific\"></a>\n### 특정 스테이시 목록에서 가져와 적용하기\n\n메세지 작성된 스테이시 리스트 먼저 확인하세요\n\n```sh\n$ git stash list\n```\n\n그런 다음 리스트 내 특정 스테이시를 적용해요\n\n```sh\n$ git stash apply \"stash@{n}\"\n```\n\n여기에서, 'n' 은 스택 안에서 스테이시의 위치를 나타내요. 젤 위에 있는 스테이시가 0 일거에요.\n\n\n## 찾아보기\n\n### 어떤 커밋에서 문자열을 찾고 싶어\n\n특정한 문자열이 포함된 어떤 커밋을 찾으려면, 이런 구조로 쓸 수 있어요:\n\n```sh\n$ git log -S \"string to find\"\n```\n\n일반적인 파라미터들은:\n\n* `--source` 각 커밋에 도달한 명령어에 지정된 참조 이름을 보여주는걸 의미해요.\n\n* `--all` 는 모든 브랜치에서 시작하는걸 의미해요.\n\n* `--reverse` 반대의 순서로 출력해요, 변경점의 첫번째 커밋이 보일꺼란 거죠.\n\n<a name=\"find-by-committer\"></a>\n### 작성자나 커미터를 찾고 싶어\n\n작성자나 커미터의 모든 커밋을 찾으려면 이렇게 쓸 수 있어요:\n\n```sh\n$ git log --author=<name or email>\n$ git log --committer=<name or email>\n```\n\n작성자와 커미터가 같지 않다는 것만 염두해두세요.\n`--author`는 코드를 실제로 코드를 작성한 사람이고\n반면에 `--committer`는 실제 작성자를 대신해 커밋을 한 사람이에요.\n\n### 특정 파일이 포함된 커밋을 목록화 하고 싶어\n\n특정 파일이 든 모든 커밋을 찾으려면 이렇게 해요:\n\n```sh\n$ git log -- <path to file>\n```\n\n보통은 정확한 경로를 쓸테지만 와일드 카드로 경로나 파일명을 쓸수도 있어요:\n\n```sh\n$ git log -- **/*.js\n```\n\n와일드 카드를 쓸 때, 커밋된 파일의 목록을 볼 수 있는 `--name-status`로 확인하는게 유용할거에요:\n\n```sh\n$ git log --name-status -- **/*.js\n```\n\n### 커밋을 참조하는 태그를 찾고 싶어\n\n특정 커밋이 포함된 모든 태그를 찾으려면:\n\n```sh\n$ git tag --contains <commitid>\n```\n\n## 서브모듈\n\n<a name=\"clone-submodules\"></a>\n### 모든 서브모듈을 클론하기\n\n```sh\n$ git clone --recursive git://github.com/foo/bar.git\n```\n\n벌써 클론했다면:\n\n```sh\n$ git submodule update --init --recursive\n```\n\n<a name=\"delete-submodule\"></a>\n### 서브모듈 지우기\n\n서브모듈을 만드는건 아주 간단하지만 지우는건 그렇진 않아요. 필요한 명령어는:\n\n```sh\n$ git submodule deinit submodulename\n$ git rm submodulename\n$ git rm --cached submodulename\n$ rm -rf .git/modules/submodulename\n```\n\n## 기타 항목들\n\n### 지운 파일 복구하기\n\n우선 그 파일이 마지막으로 있었던 커밋을 찾고:\n\n```sh\n$ git rev-list -n 1 HEAD -- filename\n```\n\n그런 다음 그 파일을 체크아웃해요\n\n```\ngit checkout deletingcommitid^ -- filename\n```\n\n### 태그 지우기\n\n```sh\n$ git tag -d <tag_name>\n$ git push <remote> :refs/tags/<tag_name>\n```\n\n<a name=\"recover-tag\"></a>\n### 지워진 태그 복구하기\n\n이미 지운 태그를 복구하고 싶다면, 이런 단계를 따라해 볼 수 있어요: 우선, 연결할 수 없는 태그를 찾고:\n\n```sh\n$ git fsck --unreachable | grep tag\n```\n\n태그의 해쉬를 메모해두세요.\n그런 다음 [`git update-ref`](https://git-scm.com/docs/git-update-ref)을 써서 지워진 태그를 복구해요:\n\n```sh\n$ git update-ref refs/tags/<tag_name> <hash>\n```\n\n이제 태그가 복구돼있을거에요.\n\n### 지워진 패치\n\n만약 깃헙에서 누군가가 풀리퀘스트를 보냈는데 이미 원래의 포크가 지워졌다면,\nurl을 쓸 수 없게 돼 레파지토리를 클론할 수 없거나 [.diff, .patch](https://github.com/blog/967-github-secrets)와 같은 `git am`를 쓸 수 없을 거에요.\n하지만 [깃헙의 특별한 참조](https://gist.github.com/piscisaureus/3342247)을 이용해서 풀 리퀘스트 자체를 확인할 수 있어요.\nPR#1의 내용을 pr_1이란 새 브랜치로 패치 받으려면:\n\n```sh\n$ git fetch origin refs/pull/1/head:pr_1\nFrom github.com:foo/bar\n * [new ref]         refs/pull/1/head -> pr_1\n```\n\n### Zip파일로 레파지토리 추출하기\n\n```sh\n$ git archive --format zip --output /full/path/to/zipfile.zip main\n```\n\n## 파일 추적하기\n\n<a name=\"change-file-name-capitalization-without-changing-contents\"></a>\n\n### 파일 내용엔 변경이 없이 파일 이름을 앞글자만 대문자로 바꾸고 싶어\n\n```sh\n(main)$ git mv --force myfile MyFile\n```\n\n### 깃 풀 받을때 로컬 파일을 덮어씌우고 싶어\n\n```sh\n(main)$ git fetch --all\n(main)$ git reset --hard origin/main\n```\n\n<a name=\"remove-from-git\"></a>\n### 파일을 로컬에는 보관하고 깃에서 지우고 싶어\n\n```sh\n(main)$ git rm --cached log.txt\n```\n\n### 특정한 버전대로 파일을 복구하고 싶어\n\n복구하고 싶은 해시가 c5f567 이라고 가정하면:\n\n```sh\n(main)$ git checkout c5f567 -- file1/to/restore file2/to/restore\n```\n\nc5f567 한 단계전으로 복구하고 싶다면, c5f567~1로 적어줘요:\n\n```sh\n(main)$ git checkout c5f567~1 -- file1/to/restore file2/to/restore\n```\n\n### 커밋과 브랜치 간의 특정 파일 변경 이력이 필요해\n\n마지막 커밋과 c5f567으로 부터의 차이를 비교하고 싶다고 가정하면:\n\n\n```sh\n$ git diff HEAD:path_to_file/file c5f567:path_to_file/file\n# 아니면 짧게:\n$ git diff HEAD c5f567 -- path_to_file/file\n```\n\n브랜치도 같은 방법으로:\n\n```sh\n$ git diff main:path_to_file/file staging:path_to_file/file\n# 아니면 짧게:\n$ git diff main staging -- path_to_file/file\n```\n\n## 설정\n\n### 깃 명령어 몇 개를 앨리어스 등록하고 싶어\n\n맥OS나 리눅스에는, 깃 설정 파일이 ```~/.gitconfig``` 에 있어요. 단축용으로 (몇개는 평소 쓰는 용도로) 앨리어스 몇개를 아래와 같이 계속 추가해오고 있어요.\n\n```vim\n[alias]\n    a = add\n    amend = commit --amend\n    c = commit\n    ca = commit --amend\n    ci = commit -a\n    co = checkout\n    d = diff\n    dc = diff --changed\n    ds = diff --staged\n    f = fetch\n    loll = log --graph --decorate --pretty=oneline --abbrev-commit\n    m = merge\n    one = log --pretty=oneline\n    outstanding = rebase -i @{u}\n    s = status\n    unpushed = log @{u}\n    wc = whatchanged\n    wip = rebase -i @{u}\n    zap = fetch -p\n```\n\n### 레파지토리에 빈 디렉토리를 추가하고 싶어\n\n못해요! 깃은 지원하지 않거든요, 근데 꼼수가 있어요. 디렉토리에에 .gitignore 파일을 아래 내용으로 만들어요:\n\n```\n # Ignore everything in this directory\n *\n # Except this file\n !.gitignore\n```\n\n다른 일반적인 컨벤션은 그 폴더 안에 .gitkeep이라는 이름의 빈 파일을 만드는 거에요.\n\n```sh\n$ mkdir mydir\n$ touch mydir/.gitkeep\n```\n\n.keep이란 이름으로도 쓸 수 있는데요, 두번째 라인이 ```touch mydir/.keep```가 되어야겠죠.\n\n### 레파지토리 유저명과 비밀번호를 캐시해두고 싶어\n\n인증이 필요한 레파지토리를 가지고 있을 텐데요.\n이런 경우 유저명과 비밀번호를 캐시할 수 있을테니 매번 푸시/풀 할 때마다 입력할 필욘 없어요.\n크리덴셜 헬퍼가 해줄거에요.\n\n```sh\n$ git config --global credential.helper cache\n# Set git to use the credential memory cache\n```\n\n```sh\n$ git config --global credential.helper 'cache --timeout=3600'\n# Set the cache to timeout after 1 hour (setting is in seconds)\n```\n\n### 깃이 권한과 파일모드 변경을 무시하게 만들고 싶어\n\n```sh\n$ git config core.fileMode false\n```\n\n이 것을 로그인된 유저의 기본 행위로 설정으로 해두려면, 이렇게 써요:\n\n```sh\n$ git config --global core.fileMode false\n```\n\n### 글로벌 유저로 설정해두고 싶어\n\n모든 로컬 레파지토리에 사용되는 유저 정보를 설정하려면, 그리고 버전 이력을 리뷰할때 알아보기 쉬운 이름으로 설정하려면:\n\n```sh\n$ git config --global user.name “[firstname lastname]”\n```\n\n각 이력 생산자에게 연관해서 이메일 설정을 해주려면:\n\n```sh\ngit config --global user.email “[valid-email]”\n```\n\n## 뭘 잘못했는지 모르겠어\n\n음, 망했군요. 뭔가를 `reset` 했거나, 다른 브랜치로 머지했거나, 지금은 찾질 못하는 커밋으로 강제 푸시를 해버렸군요.\n알다시피, 어떤 시점에선, 잘 하고 있었고 거기로 돌아가고 싶겠죠.\n이게 바로 `git reflog`의 존재이유에요.  `reflog` 는 브랜치 끝의 어떤 변경점이든 브랜치나 태그에 의해 참조되지 않더라도 다 보관해요.\n기본적으로, HEAD가 변경되는 모든 경우, 리플로그에 새로운 입력이 추가돼요. 아쉽게도 이 기능은 로컬 레파지토리에서만 동작해고, 오직 움직임만을 트래킹해요 (예를 들자면 어디에도 기록되지 않았던 파일의 변경은 아니에요)\n\n```sh\n(main)$ git reflog\n0a2e358 HEAD@{0}: reset: moving to HEAD~2\n0254ea7 HEAD@{1}: checkout: moving from 2.2 to main\nc10f740 HEAD@{2}: checkout: moving from main to 2.2\n```\n\n이 리플로그는 마스터에서 2.2 브랜치로 체크아웃하고 되돌린 것을 보여주네요.\n저기에선, 오래된 커밋으로 리셋하기 어려워요. 최신 활동이 `HEAD@{0}` 상단 라벨로 보여지네요.\n\n만약 실수로 뒤로 이동했다면,\n리플로그는 실수로 지워진 2개의 커밋 전 상태인 (0254ea7)를 가리키는 커밋 마스터를 포함할거에요.\n\n```sh\n$ git reset --hard 0254ea7\n```\n\n`git reset`을 쓰는 것으로 마스터를 이전 커밋으로 되돌릴 수 있어요.\n이력이 실수로 변경됐을 때의 안정망을 제공할거에요.\n\n([여기](https://www.atlassian.com/git/tutorials/rewriting-history/git-reflog)에서 복제해와 수정했어요).\n\n\n# 다른 리소스\n\n## 도서\n\n* [Pro Git](https://git-scm.com/book/en/v2) - Scott Chacon 과 Ben Straub의 훌륭한 깃 책\n* [Git Internals](https://github.com/pluralsight/git-internals-pdf) - Scott Chacon의 또다른 훌륭한 깃 책\n\n## 튜토리얼\n\n* [Atlassian's Git tutorial](https://www.atlassian.com/git/tutorials) 기초부터 고급까지 튜토리얼과 함께 하는 깃 제대로 얻기\n* [Learn Git branching](https://learngitbranching.js.org/) 대화형 웹 기반의 브랜치/머지/리베이스 튜토리얼\n* [Getting solid at Git rebase vs. merge](https://medium.com/@porteneuve/getting-solid-at-git-rebase-vs-merge-4fa1a48c53aa)\n* [git-workflow](https://github.com/asmeurer/git-workflow) - [Aaron Meurer](https://github.com/asmeurer)의 어떻게 깃을 통해 오픈소스 레파지토리에 어떻게 기여할까\n* [GitHub as a workflow](https://hugogiraudel.com/2015/08/13/github-as-a-workflow/) - 깃헙을 워크플로우로 쓰는 흥미로운 작업, 특히 빈 풀 리퀘스트를 활용하는\n* [Githug](https://github.com/Gazler/githug) - 더 일반적인 깃 워크플로우를 배우는 게임\n\n## 스크립트와 도구\n\n* [firstaidgit.io](http://firstaidgit.io/) 가장 많이 묻는 깃 질문의, 검색가능한 모음\n* [git-extra-commands](https://github.com/unixorn/git-extra-commands) - 유용한 기타 깃 스크립트 모음\n* [git-extras](https://github.com/tj/git-extras) - 깃 유틸리티 -- 레파지토리 요약, repl, 변경이력 밀집도, 작성자 커밋 비율 등\n* [git-fire](https://github.com/qw3rtman/git-fire) - git-fire는 모든 현재 파일을 추가,커밋,새 브랜치로 푸시(머지를 예방하기 위한) 등 비상사태를 도와주는 플러그인\n* [git-tips](https://github.com/git-tips/tips) - 자그마한 깃 팁들\n* [git-town](https://github.com/Originate/git-town) - 포괄적이고, 높은 수준의 깃 워크플로우 지원! http://www.git-town.com\n\n## GUI 클라이언트\n\n* [GitKraken](https://www.gitkraken.com/) - 완전 고급의 깃 클라이언트 Windows, Mac & Linux\n* [git-cola](https://git-cola.github.io/) - 또 다른 깃 클라이언트 Windows, OS X\n* [GitUp](https://github.com/git-up/GitUp) - 아주 독단적으로 방식으로 깃의 복잡함을 다루는 새로운 GUI\n* [gitx-dev](https://rowanj.github.io/gitx/) - 또다른 그래픽적인 깃 클라이언트 OS X\n* [Sourcetree](https://www.sourcetreeapp.com/) - 아름답고 무료인 깃 GUI 안에서 단순함과 강력함이 만났어 Windows and Mac\n* [Tower](https://www.git-tower.com/) - 그래픽 Git 클라이언트 OS X (유료)\n* [tig](https://jonas.github.io/tig/) - 깃을 위한 터민러 텍스트 모드 인터페이스\n* [Magit](https://magit.vc/) - Emacs 패키지를 위해 구현된 깃 인터페이스\n* [GitExtensions](https://github.com/gitextensions/gitextensions) - 쉘 확장, 비주얼 스투디오 2010-2015 플러그인 그리고 독자적인 깃 레파지토리 도구\n* [Fork](https://git-fork.com/) - 빠르고 친숙한 깃 클라이언트 Mac (베타)\n* [gmaster](https://gmaster.io/) - 3-way 머지, 리팩터 분석기, 시멘틱 diff와 머지 기능의 윈도 전용 깃 클라이언트 (베타)\n* [gitk](https://git-scm.com/docs/gitk) - 간단한 레파지토리 상태를 볼 수 있는 리눅스 깃 클라이언트\n"
  },
  {
    "path": "README_ru.md",
    "content": "# Правила полета на Git\n\n🌍\n*[English](README.md) ∙ [Español](README_es.md)  ∙  [Русский](README_ru.md) ∙ [繁體中文](README_zh-TW.md) ∙ [简体中文](README_zh-CN.md) ∙ [한국어](README_kr.md)  ∙  [Tiếng Việt](README_vi.md) ∙ [Français](README_fr.md) ∙ [日本語](README_ja.md)*\n\n#### Что это за \"правила полета\" такие?\n\nЕсть инструкции для астронавтов (а здесь подобное руководство для пользователей Git) о том, как быть, если что-то пошло не так.\n\n> *Полетные правила* - это с большим трудом полученный запас знаний, записанный в форме инструкций, в которых указан последовательный порядок действий в разных ситуациях и сказано, почему нужно делать именно так. По сути это крайне подробный, стандартный план действий в ситуациях, развивающихся по прописанным сценариям. [...]\n\n> В НАСА фиксируют все наши промахи, аварии и методы решения проблем с начала 1960 х гг., когда наземные группы проекта Mercury начали составлять сборник \"выученных уроков\". Теперь в этом сборнике перечислены тысячи сложных ситуаций и их решения – от отказа двигателей, поломки ручек люка до проблем с компьютером.\n\n— Крис Хэдфилд, *Руководство астронавта по жизни на Земле* (перевод Дмитрия Лазарева).\n\n#### Соглашения для этого документа\n\nДля наглядности во всех примерах в этом документе используется измененное приглашение командной строки, чтобы показать текущую ветку и есть ли подготовленные изменения. Ветка заключена в кавычки, а символ `*` после ветки означает подготовленные изменения.\n\nПриведенные команды работают на Git версии 2.13.0 и выше. Для обновления Вашей версии Git посетите [вебсайт Git](https://www.git-scm.com/).\n\n[![Заходите в чат https://gitter.im/k88hudson/git-flight-rules](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/k88hudson/git-flight-rules?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n\n  - [Репозитории](#%D0%A0%D0%B5%D0%BF%D0%BE%D0%B7%D0%B8%D1%82%D0%BE%D1%80%D0%B8%D0%B8)\n    - [Я хочу создать локальный репозиторий](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D1%81%D0%BE%D0%B7%D0%B4%D0%B0%D1%82%D1%8C-%D0%BB%D0%BE%D0%BA%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D0%B9-%D1%80%D0%B5%D0%BF%D0%BE%D0%B7%D0%B8%D1%82%D0%BE%D1%80%D0%B8%D0%B9)\n    - [Я хочу клонировать удаленный репозиторий](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D0%BA%D0%BB%D0%BE%D0%BD%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D1%82%D1%8C-%D1%83%D0%B4%D0%B0%D0%BB%D0%B5%D0%BD%D0%BD%D1%8B%D0%B9-%D1%80%D0%B5%D0%BF%D0%BE%D0%B7%D0%B8%D1%82%D0%BE%D1%80%D0%B8%D0%B9)\n    - [Я неправильно задал удаленный репозиторий](#%D0%AF-%D0%BD%D0%B5%D0%BF%D1%80%D0%B0%D0%B2%D0%B8%D0%BB%D1%8C%D0%BD%D0%BE-%D0%B7%D0%B0%D0%B4%D0%B0%D0%BB-%D1%83%D0%B4%D0%B0%D0%BB%D0%B5%D0%BD%D0%BD%D1%8B%D0%B9-%D1%80%D0%B5%D0%BF%D0%BE%D0%B7%D0%B8%D1%82%D0%BE%D1%80%D0%B8%D0%B9)\n    - [Я хочу добавить код в чужой репозиторий](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D0%B4%D0%BE%D0%B1%D0%B0%D0%B2%D0%B8%D1%82%D1%8C-%D0%BA%D0%BE%D0%B4-%D0%B2-%D1%87%D1%83%D0%B6%D0%BE%D0%B9-%D1%80%D0%B5%D0%BF%D0%BE%D0%B7%D0%B8%D1%82%D0%BE%D1%80%D0%B8%D0%B9)\n      - [Предложение кода с помощью пулл-реквестов](#%D0%9F%D1%80%D0%B5%D0%B4%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5-%D0%BA%D0%BE%D0%B4%D0%B0-%D1%81-%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E-%D0%BF%D1%83%D0%BB%D0%BB-%D1%80%D0%B5%D0%BA%D0%B2%D0%B5%D1%81%D1%82%D0%BE%D0%B2)\n      - [Мне нужно обновить свой форк последними изменениями из исходного репозитория](#%D0%9C%D0%BD%D0%B5-%D0%BD%D1%83%D0%B6%D0%BD%D0%BE-%D0%BE%D0%B1%D0%BD%D0%BE%D0%B2%D0%B8%D1%82%D1%8C-%D1%81%D0%B2%D0%BE%D0%B9-%D1%84%D0%BE%D1%80%D0%BA-%D0%BF%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D0%BD%D0%B8%D0%BC%D0%B8-%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F%D0%BC%D0%B8-%D0%B8%D0%B7-%D0%B8%D1%81%D1%85%D0%BE%D0%B4%D0%BD%D0%BE%D0%B3%D0%BE-%D1%80%D0%B5%D0%BF%D0%BE%D0%B7%D0%B8%D1%82%D0%BE%D1%80%D0%B8%D1%8F)\n  - [Редактирование коммитов](#%D0%A0%D0%B5%D0%B4%D0%B0%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D0%BA%D0%BE%D0%BC%D0%BC%D0%B8%D1%82%D0%BE%D0%B2)\n    - [Что я только что сохранил?](#%D0%A7%D1%82%D0%BE-%D1%8F-%D1%82%D0%BE%D0%BB%D1%8C%D0%BA%D0%BE-%D1%87%D1%82%D0%BE-%D1%81%D0%BE%D1%85%D1%80%D0%B0%D0%BD%D0%B8%D0%BB)\n    - [Я неправильно написал сообщение коммита](#%D0%AF-%D0%BD%D0%B5%D0%BF%D1%80%D0%B0%D0%B2%D0%B8%D0%BB%D1%8C%D0%BD%D0%BE-%D0%BD%D0%B0%D0%BF%D0%B8%D1%81%D0%B0%D0%BB-%D1%81%D0%BE%D0%BE%D0%B1%D1%89%D0%B5%D0%BD%D0%B8%D0%B5-%D0%BA%D0%BE%D0%BC%D0%BC%D0%B8%D1%82%D0%B0)\n    - [Я сделал коммит с неправильным именем автора и адресом электронной почты](#%D0%AF-%D1%81%D0%B4%D0%B5%D0%BB%D0%B0%D0%BB-%D0%BA%D0%BE%D0%BC%D0%BC%D0%B8%D1%82-%D1%81-%D0%BD%D0%B5%D0%BF%D1%80%D0%B0%D0%B2%D0%B8%D0%BB%D1%8C%D0%BD%D1%8B%D0%BC-%D0%B8%D0%BC%D0%B5%D0%BD%D0%B5%D0%BC-%D0%B0%D0%B2%D1%82%D0%BE%D1%80%D0%B0-%D0%B8-%D0%B0%D0%B4%D1%80%D0%B5%D1%81%D0%BE%D0%BC-%D1%8D%D0%BB%D0%B5%D0%BA%D1%82%D1%80%D0%BE%D0%BD%D0%BD%D0%BE%D0%B9-%D0%BF%D0%BE%D1%87%D1%82%D1%8B)\n    - [Я хочу удалить файл из предыдущего коммита](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D1%83%D0%B4%D0%B0%D0%BB%D0%B8%D1%82%D1%8C-%D1%84%D0%B0%D0%B9%D0%BB-%D0%B8%D0%B7-%D0%BF%D1%80%D0%B5%D0%B4%D1%8B%D0%B4%D1%83%D1%89%D0%B5%D0%B3%D0%BE-%D0%BA%D0%BE%D0%BC%D0%BC%D0%B8%D1%82%D0%B0)\n    - [Я хочу удалить последний коммит](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D1%83%D0%B4%D0%B0%D0%BB%D0%B8%D1%82%D1%8C-%D0%BF%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D0%BD%D0%B8%D0%B9-%D0%BA%D0%BE%D0%BC%D0%BC%D0%B8%D1%82)\n    - [Удалить произвольный коммит](#%D0%A3%D0%B4%D0%B0%D0%BB%D0%B8%D1%82%D1%8C-%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%BB%D1%8C%D0%BD%D1%8B%D0%B9-%D0%BA%D0%BE%D0%BC%D0%BC%D0%B8%D1%82)\n    - [Я пытаюсь опубликовать исправленный коммит, но получаю сообщение об ошибке](#%D0%AF-%D0%BF%D1%8B%D1%82%D0%B0%D1%8E%D1%81%D1%8C-%D0%BE%D0%BF%D1%83%D0%B1%D0%BB%D0%B8%D0%BA%D0%BE%D0%B2%D0%B0%D1%82%D1%8C-%D0%B8%D1%81%D0%BF%D1%80%D0%B0%D0%B2%D0%BB%D0%B5%D0%BD%D0%BD%D1%8B%D0%B9-%D0%BA%D0%BE%D0%BC%D0%BC%D0%B8%D1%82-%D0%BD%D0%BE-%D0%BF%D0%BE%D0%BB%D1%83%D1%87%D0%B0%D1%8E-%D1%81%D0%BE%D0%BE%D0%B1%D1%89%D0%B5%D0%BD%D0%B8%D0%B5-%D0%BE%D0%B1-%D0%BE%D1%88%D0%B8%D0%B1%D0%BA%D0%B5)\n    - [Я случайно сделал жесткий сброс (--hard) и теперь хочу вернуть свои изменения](#%D0%AF-%D1%81%D0%BB%D1%83%D1%87%D0%B0%D0%B9%D0%BD%D0%BE-%D1%81%D0%B4%D0%B5%D0%BB%D0%B0%D0%BB-%D0%B6%D0%B5%D1%81%D1%82%D0%BA%D0%B8%D0%B9-%D1%81%D0%B1%D1%80%D0%BE%D1%81---hard-%D0%B8-%D1%82%D0%B5%D0%BF%D0%B5%D1%80%D1%8C-%D1%85%D0%BE%D1%87%D1%83-%D0%B2%D0%B5%D1%80%D0%BD%D1%83%D1%82%D1%8C-%D1%81%D0%B2%D0%BE%D0%B8-%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F)\n    - [Я случайно опубликовал ненужное слияние](#%D0%AF-%D1%81%D0%BB%D1%83%D1%87%D0%B0%D0%B9%D0%BD%D0%BE-%D0%BE%D0%BF%D1%83%D0%B1%D0%BB%D0%B8%D0%BA%D0%BE%D0%B2%D0%B0%D0%BB-%D0%BD%D0%B5%D0%BD%D1%83%D0%B6%D0%BD%D0%BE%D0%B5-%D1%81%D0%BB%D0%B8%D1%8F%D0%BD%D0%B8%D0%B5)\n    - [Я случайно закоммитил и опубликовал файлы с конфиденциальными данными](#%D0%AF-%D1%81%D0%BB%D1%83%D1%87%D0%B0%D0%B9%D0%BD%D0%BE-%D0%B7%D0%B0%D0%BA%D0%BE%D0%BC%D0%BC%D0%B8%D1%82%D0%B8%D0%BB-%D0%B8-%D0%BE%D0%BF%D1%83%D0%B1%D0%BB%D0%B8%D0%BA%D0%BE%D0%B2%D0%B0%D0%BB-%D1%84%D0%B0%D0%B9%D0%BB%D1%8B-%D1%81-%D0%BA%D0%BE%D0%BD%D1%84%D0%B8%D0%B4%D0%B5%D0%BD%D1%86%D0%B8%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D0%BC%D0%B8-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D0%BC%D0%B8)\n    - [Я хочу удалить большой файл из истории репозитория](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D1%83%D0%B4%D0%B0%D0%BB%D0%B8%D1%82%D1%8C-%D0%B1%D0%BE%D0%BB%D1%8C%D1%88%D0%BE%D0%B9-%D1%84%D0%B0%D0%B9%D0%BB-%D0%B8%D0%B7-%D0%B8%D1%81%D1%82%D0%BE%D1%80%D0%B8%D0%B8-%D1%80%D0%B5%D0%BF%D0%BE%D0%B7%D0%B8%D1%82%D0%BE%D1%80%D0%B8%D1%8F)\n      - [Рекомендуемый способ: Использование bfg](#%D0%A0%D0%B5%D0%BA%D0%BE%D0%BC%D0%B5%D0%BD%D0%B4%D1%83%D0%B5%D0%BC%D1%8B%D0%B9-%D1%81%D0%BF%D0%BE%D1%81%D0%BE%D0%B1-%D0%98%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-bfg)\n      - [Встроенный способ: Использование git-filter-branch](#%D0%92%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%BD%D1%8B%D0%B9-%D1%81%D0%BF%D0%BE%D1%81%D0%BE%D0%B1-%D0%98%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-git-filter-branch)\n      - [Финальный шаг: Публикация измененной истории репозитория](#%D0%A4%D0%B8%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D0%B9-%D1%88%D0%B0%D0%B3-%D0%9F%D1%83%D0%B1%D0%BB%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F-%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D0%B5%D0%BD%D0%BD%D0%BE%D0%B9-%D0%B8%D1%81%D1%82%D0%BE%D1%80%D0%B8%D0%B8-%D1%80%D0%B5%D0%BF%D0%BE%D0%B7%D0%B8%D1%82%D0%BE%D1%80%D0%B8%D1%8F)\n    - [Мне нужно изменить содержимое коммита, который не является последним](#%D0%9C%D0%BD%D0%B5-%D0%BD%D1%83%D0%B6%D0%BD%D0%BE-%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D0%B8%D1%82%D1%8C-%D1%81%D0%BE%D0%B4%D0%B5%D1%80%D0%B6%D0%B8%D0%BC%D0%BE%D0%B5-%D0%BA%D0%BE%D0%BC%D0%BC%D0%B8%D1%82%D0%B0-%D0%BA%D0%BE%D1%82%D0%BE%D1%80%D1%8B%D0%B9-%D0%BD%D0%B5-%D1%8F%D0%B2%D0%BB%D1%8F%D0%B5%D1%82%D1%81%D1%8F-%D0%BF%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D0%BD%D0%B8%D0%BC)\n  - [Подготовка изменений (staging)](#%D0%9F%D0%BE%D0%B4%D0%B3%D0%BE%D1%82%D0%BE%D0%B2%D0%BA%D0%B0-%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D0%B5%D0%BD%D0%B8%D0%B9-staging)\n    - [Мне нужно добавить подготовленные изменения в предыдущий коммит](#%D0%9C%D0%BD%D0%B5-%D0%BD%D1%83%D0%B6%D0%BD%D0%BE-%D0%B4%D0%BE%D0%B1%D0%B0%D0%B2%D0%B8%D1%82%D1%8C-%D0%BF%D0%BE%D0%B4%D0%B3%D0%BE%D1%82%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%BD%D1%8B%D0%B5-%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F-%D0%B2-%D0%BF%D1%80%D0%B5%D0%B4%D1%8B%D0%B4%D1%83%D1%89%D0%B8%D0%B9-%D0%BA%D0%BE%D0%BC%D0%BC%D0%B8%D1%82)\n    - [Я хочу подготовить только часть файла, а не весь файл целиком](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D0%BF%D0%BE%D0%B4%D0%B3%D0%BE%D1%82%D0%BE%D0%B2%D0%B8%D1%82%D1%8C-%D1%82%D0%BE%D0%BB%D1%8C%D0%BA%D0%BE-%D1%87%D0%B0%D1%81%D1%82%D1%8C-%D1%84%D0%B0%D0%B9%D0%BB%D0%B0-%D0%B0-%D0%BD%D0%B5-%D0%B2%D0%B5%D1%81%D1%8C-%D1%84%D0%B0%D0%B9%D0%BB-%D1%86%D0%B5%D0%BB%D0%B8%D0%BA%D0%BE%D0%BC)\n    - [Я хочу добавить изменения одного файла в два разных коммита](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D0%B4%D0%BE%D0%B1%D0%B0%D0%B2%D0%B8%D1%82%D1%8C-%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F-%D0%BE%D0%B4%D0%BD%D0%BE%D0%B3%D0%BE-%D1%84%D0%B0%D0%B9%D0%BB%D0%B0-%D0%B2-%D0%B4%D0%B2%D0%B0-%D1%80%D0%B0%D0%B7%D0%BD%D1%8B%D1%85-%D0%BA%D0%BE%D0%BC%D0%BC%D0%B8%D1%82%D0%B0)\n    - [Я подготовил слишком много правок и теперь хочу разделить их на несколько отдельных коммитов](#%D0%AF-%D0%BF%D0%BE%D0%B4%D0%B3%D0%BE%D1%82%D0%BE%D0%B2%D0%B8%D0%BB-%D1%81%D0%BB%D0%B8%D1%88%D0%BA%D0%BE%D0%BC-%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE-%D0%BF%D1%80%D0%B0%D0%B2%D0%BE%D0%BA-%D0%B8-%D1%82%D0%B5%D0%BF%D0%B5%D1%80%D1%8C-%D1%85%D0%BE%D1%87%D1%83-%D1%80%D0%B0%D0%B7%D0%B4%D0%B5%D0%BB%D0%B8%D1%82%D1%8C-%D0%B8%D1%85-%D0%BD%D0%B0-%D0%BD%D0%B5%D1%81%D0%BA%D0%BE%D0%BB%D1%8C%D0%BA%D0%BE-%D0%BE%D1%82%D0%B4%D0%B5%D0%BB%D1%8C%D0%BD%D1%8B%D1%85-%D0%BA%D0%BE%D0%BC%D0%BC%D0%B8%D1%82%D0%BE%D0%B2)\n    - [Я хочу подготовить свои неподготовленные правки и убрать из подготовки то, что уже подготовлено](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D0%BF%D0%BE%D0%B4%D0%B3%D0%BE%D1%82%D0%BE%D0%B2%D0%B8%D1%82%D1%8C-%D1%81%D0%B2%D0%BE%D0%B8-%D0%BD%D0%B5%D0%BF%D0%BE%D0%B4%D0%B3%D0%BE%D1%82%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%BD%D1%8B%D0%B5-%D0%BF%D1%80%D0%B0%D0%B2%D0%BA%D0%B8-%D0%B8-%D1%83%D0%B1%D1%80%D0%B0%D1%82%D1%8C-%D0%B8%D0%B7-%D0%BF%D0%BE%D0%B4%D0%B3%D0%BE%D1%82%D0%BE%D0%B2%D0%BA%D0%B8-%D1%82%D0%BE-%D1%87%D1%82%D0%BE-%D1%83%D0%B6%D0%B5-%D0%BF%D0%BE%D0%B4%D0%B3%D0%BE%D1%82%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%BE)\n  - [Неподготовленные правки](#%D0%9D%D0%B5%D0%BF%D0%BE%D0%B4%D0%B3%D0%BE%D1%82%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%BD%D1%8B%D0%B5-%D0%BF%D1%80%D0%B0%D0%B2%D0%BA%D0%B8)\n    - [Я хочу переместить мои неподготовленные правки в новую ветку](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D0%BF%D0%B5%D1%80%D0%B5%D0%BC%D0%B5%D1%81%D1%82%D0%B8%D1%82%D1%8C-%D0%BC%D0%BE%D0%B8-%D0%BD%D0%B5%D0%BF%D0%BE%D0%B4%D0%B3%D0%BE%D1%82%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%BD%D1%8B%D0%B5-%D0%BF%D1%80%D0%B0%D0%B2%D0%BA%D0%B8-%D0%B2-%D0%BD%D0%BE%D0%B2%D1%83%D1%8E-%D0%B2%D0%B5%D1%82%D0%BA%D1%83)\n    - [Я хочу переместить неподготовленные правки в другую существующую ветку](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D0%BF%D0%B5%D1%80%D0%B5%D0%BC%D0%B5%D1%81%D1%82%D0%B8%D1%82%D1%8C-%D0%BD%D0%B5%D0%BF%D0%BE%D0%B4%D0%B3%D0%BE%D1%82%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%BD%D1%8B%D0%B5-%D0%BF%D1%80%D0%B0%D0%B2%D0%BA%D0%B8-%D0%B2-%D0%B4%D1%80%D1%83%D0%B3%D1%83%D1%8E-%D1%81%D1%83%D1%89%D0%B5%D1%81%D1%82%D0%B2%D1%83%D1%8E%D1%89%D1%83%D1%8E-%D0%B2%D0%B5%D1%82%D0%BA%D1%83)\n    - [Я хочу отменить мои локальные несохраненные изменения (подготовленные и неподготовленные)](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D0%BE%D1%82%D0%BC%D0%B5%D0%BD%D0%B8%D1%82%D1%8C-%D0%BC%D0%BE%D0%B8-%D0%BB%D0%BE%D0%BA%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D0%B5-%D0%BD%D0%B5%D1%81%D0%BE%D1%85%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%BD%D1%8B%D0%B5-%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F-%D0%BF%D0%BE%D0%B4%D0%B3%D0%BE%D1%82%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%BD%D1%8B%D0%B5-%D0%B8-%D0%BD%D0%B5%D0%BF%D0%BE%D0%B4%D0%B3%D0%BE%D1%82%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%BD%D1%8B%D0%B5)\n    - [Я хочу отменить некоторые неподготовленные изменения](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D0%BE%D1%82%D0%BC%D0%B5%D0%BD%D0%B8%D1%82%D1%8C-%D0%BD%D0%B5%D0%BA%D0%BE%D1%82%D0%BE%D1%80%D1%8B%D0%B5-%D0%BD%D0%B5%D0%BF%D0%BE%D0%B4%D0%B3%D0%BE%D1%82%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%BD%D1%8B%D0%B5-%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F)\n    - [Я хочу отбросить неподготовленные изменения в некоторых файлах](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D0%BE%D1%82%D0%B1%D1%80%D0%BE%D1%81%D0%B8%D1%82%D1%8C-%D0%BD%D0%B5%D0%BF%D0%BE%D0%B4%D0%B3%D0%BE%D1%82%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%BD%D1%8B%D0%B5-%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F-%D0%B2-%D0%BD%D0%B5%D0%BA%D0%BE%D1%82%D0%BE%D1%80%D1%8B%D1%85-%D1%84%D0%B0%D0%B9%D0%BB%D0%B0%D1%85)\n    - [Я хочу убрать все неподготовленные локальные изменения](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D1%83%D0%B1%D1%80%D0%B0%D1%82%D1%8C-%D0%B2%D1%81%D0%B5-%D0%BD%D0%B5%D0%BF%D0%BE%D0%B4%D0%B3%D0%BE%D1%82%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%BD%D1%8B%D0%B5-%D0%BB%D0%BE%D0%BA%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D0%B5-%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F)\n    - [Я хочу удалить все неотслеживаемые файлы](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D1%83%D0%B4%D0%B0%D0%BB%D0%B8%D1%82%D1%8C-%D0%B2%D1%81%D0%B5-%D0%BD%D0%B5%D0%BE%D1%82%D1%81%D0%BB%D0%B5%D0%B6%D0%B8%D0%B2%D0%B0%D0%B5%D0%BC%D1%8B%D0%B5-%D1%84%D0%B0%D0%B9%D0%BB%D1%8B)\n    - [Я хочу убрать заданный файл из подготовленного](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D1%83%D0%B1%D1%80%D0%B0%D1%82%D1%8C-%D0%B7%D0%B0%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9-%D1%84%D0%B0%D0%B9%D0%BB-%D0%B8%D0%B7-%D0%BF%D0%BE%D0%B4%D0%B3%D0%BE%D1%82%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%BD%D0%BE%D0%B3%D0%BE)\n  - [Ветки](#%D0%92%D0%B5%D1%82%D0%BA%D0%B8)\n    - [Я хочу получить список всех веток](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D0%BF%D0%BE%D0%BB%D1%83%D1%87%D0%B8%D1%82%D1%8C-%D1%81%D0%BF%D0%B8%D1%81%D0%BE%D0%BA-%D0%B2%D1%81%D0%B5%D1%85-%D0%B2%D0%B5%D1%82%D0%BE%D0%BA)\n    - [Создать ветку на определенном коммите](#%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D1%82%D1%8C-%D0%B2%D0%B5%D1%82%D0%BA%D1%83-%D0%BD%D0%B0-%D0%BE%D0%BF%D1%80%D0%B5%D0%B4%D0%B5%D0%BB%D0%B5%D0%BD%D0%BD%D0%BE%D0%BC-%D0%BA%D0%BE%D0%BC%D0%BC%D0%B8%D1%82%D0%B5)\n    - [Я стянул изменения (pull) из неправильной ветки или в неправильную ветку](#%D0%AF-%D1%81%D1%82%D1%8F%D0%BD%D1%83%D0%BB-%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F-pull-%D0%B8%D0%B7-%D0%BD%D0%B5%D0%BF%D1%80%D0%B0%D0%B2%D0%B8%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9-%D0%B2%D0%B5%D1%82%D0%BA%D0%B8-%D0%B8%D0%BB%D0%B8-%D0%B2-%D0%BD%D0%B5%D0%BF%D1%80%D0%B0%D0%B2%D0%B8%D0%BB%D1%8C%D0%BD%D1%83%D1%8E-%D0%B2%D0%B5%D1%82%D0%BA%D1%83)\n    - [Я хочу отменить локальные коммиты, чтобы моя ветка стала такой же как на сервере](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D0%BE%D1%82%D0%BC%D0%B5%D0%BD%D0%B8%D1%82%D1%8C-%D0%BB%D0%BE%D0%BA%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D0%B5-%D0%BA%D0%BE%D0%BC%D0%BC%D0%B8%D1%82%D1%8B-%D1%87%D1%82%D0%BE%D0%B1%D1%8B-%D0%BC%D0%BE%D1%8F-%D0%B2%D0%B5%D1%82%D0%BA%D0%B0-%D1%81%D1%82%D0%B0%D0%BB%D0%B0-%D1%82%D0%B0%D0%BA%D0%BE%D0%B9-%D0%B6%D0%B5-%D0%BA%D0%B0%D0%BA-%D0%BD%D0%B0-%D1%81%D0%B5%D1%80%D0%B2%D0%B5%D1%80%D0%B5)\n    - [Я сохранил коммит в ветку main вместо новой ветки](#%D0%AF-%D1%81%D0%BE%D1%85%D1%80%D0%B0%D0%BD%D0%B8%D0%BB-%D0%BA%D0%BE%D0%BC%D0%BC%D0%B8%D1%82-%D0%B2-%D0%B2%D0%B5%D1%82%D0%BA%D1%83-main-%D0%B2%D0%BC%D0%B5%D1%81%D1%82%D0%BE-%D0%BD%D0%BE%D0%B2%D0%BE%D0%B9-%D0%B2%D0%B5%D1%82%D0%BA%D0%B8)\n    - [Я хочу сохранить файл целиком из другого ref-ish](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D1%81%D0%BE%D1%85%D1%80%D0%B0%D0%BD%D0%B8%D1%82%D1%8C-%D1%84%D0%B0%D0%B9%D0%BB-%D1%86%D0%B5%D0%BB%D0%B8%D0%BA%D0%BE%D0%BC-%D0%B8%D0%B7-%D0%B4%D1%80%D1%83%D0%B3%D0%BE%D0%B3%D0%BE-ref-ish)\n    - [Я сделал несколько коммитов в одной ветке, а нужно было сохранять их в разных ветках](#%D0%AF-%D1%81%D0%B4%D0%B5%D0%BB%D0%B0%D0%BB-%D0%BD%D0%B5%D1%81%D0%BA%D0%BE%D0%BB%D1%8C%D0%BA%D0%BE-%D0%BA%D0%BE%D0%BC%D0%BC%D0%B8%D1%82%D0%BE%D0%B2-%D0%B2-%D0%BE%D0%B4%D0%BD%D0%BE%D0%B9-%D0%B2%D0%B5%D1%82%D0%BA%D0%B5-%D0%B0-%D0%BD%D1%83%D0%B6%D0%BD%D0%BE-%D0%B1%D1%8B%D0%BB%D0%BE-%D1%81%D0%BE%D1%85%D1%80%D0%B0%D0%BD%D1%8F%D1%82%D1%8C-%D0%B8%D1%85-%D0%B2-%D1%80%D0%B0%D0%B7%D0%BD%D1%8B%D1%85-%D0%B2%D0%B5%D1%82%D0%BA%D0%B0%D1%85)\n    - [Я хочу удалить локальные ветки, которые были удалены в upstream](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D1%83%D0%B4%D0%B0%D0%BB%D0%B8%D1%82%D1%8C-%D0%BB%D0%BE%D0%BA%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D0%B5-%D0%B2%D0%B5%D1%82%D0%BA%D0%B8-%D0%BA%D0%BE%D1%82%D0%BE%D1%80%D1%8B%D0%B5-%D0%B1%D1%8B%D0%BB%D0%B8-%D1%83%D0%B4%D0%B0%D0%BB%D0%B5%D0%BD%D1%8B-%D0%B2-upstream)\n    - [Я нечаянно удалил мою ветку](#%D0%AF-%D0%BD%D0%B5%D1%87%D0%B0%D1%8F%D0%BD%D0%BD%D0%BE-%D1%83%D0%B4%D0%B0%D0%BB%D0%B8%D0%BB-%D0%BC%D0%BE%D1%8E-%D0%B2%D0%B5%D1%82%D0%BA%D1%83)\n    - [Я хочу удалить ветку](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D1%83%D0%B4%D0%B0%D0%BB%D0%B8%D1%82%D1%8C-%D0%B2%D0%B5%D1%82%D0%BA%D1%83)\n    - [Я хочу удалить несколько веток](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D1%83%D0%B4%D0%B0%D0%BB%D0%B8%D1%82%D1%8C-%D0%BD%D0%B5%D1%81%D0%BA%D0%BE%D0%BB%D1%8C%D0%BA%D0%BE-%D0%B2%D0%B5%D1%82%D0%BE%D0%BA)\n    - [Я хочу переименовать ветку](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D0%BF%D0%B5%D1%80%D0%B5%D0%B8%D0%BC%D0%B5%D0%BD%D0%BE%D0%B2%D0%B0%D1%82%D1%8C-%D0%B2%D0%B5%D1%82%D0%BA%D1%83)\n    - [Я хочу перейти на удаленную ветку, над которой работает кто-то еще](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D0%BF%D0%B5%D1%80%D0%B5%D0%B9%D1%82%D0%B8-%D0%BD%D0%B0-%D1%83%D0%B4%D0%B0%D0%BB%D0%B5%D0%BD%D0%BD%D1%83%D1%8E-%D0%B2%D0%B5%D1%82%D0%BA%D1%83-%D0%BD%D0%B0%D0%B4-%D0%BA%D0%BE%D1%82%D0%BE%D1%80%D0%BE%D0%B9-%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%B0%D0%B5%D1%82-%D0%BA%D1%82%D0%BE-%D1%82%D0%BE-%D0%B5%D1%89%D0%B5)\n    - [Я хочу создать новую удаленную ветку из текущей локальной](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D1%81%D0%BE%D0%B7%D0%B4%D0%B0%D1%82%D1%8C-%D0%BD%D0%BE%D0%B2%D1%83%D1%8E-%D1%83%D0%B4%D0%B0%D0%BB%D0%B5%D0%BD%D0%BD%D1%83%D1%8E-%D0%B2%D0%B5%D1%82%D0%BA%D1%83-%D0%B8%D0%B7-%D1%82%D0%B5%D0%BA%D1%83%D1%89%D0%B5%D0%B9-%D0%BB%D0%BE%D0%BA%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9)\n    - [Я хочу настроить локальную ветку на отслеживание удаленной (upstream) ветки](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D0%BD%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B8%D1%82%D1%8C-%D0%BB%D0%BE%D0%BA%D0%B0%D0%BB%D1%8C%D0%BD%D1%83%D1%8E-%D0%B2%D0%B5%D1%82%D0%BA%D1%83-%D0%BD%D0%B0-%D0%BE%D1%82%D1%81%D0%BB%D0%B5%D0%B6%D0%B8%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D1%83%D0%B4%D0%B0%D0%BB%D0%B5%D0%BD%D0%BD%D0%BE%D0%B9-upstream-%D0%B2%D0%B5%D1%82%D0%BA%D0%B8)\n    - [Я хочу настроить HEAD на отслеживание основной удаленной ветки](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D0%BD%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B8%D1%82%D1%8C-head-%D0%BD%D0%B0-%D0%BE%D1%82%D1%81%D0%BB%D0%B5%D0%B6%D0%B8%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D0%BE%D1%81%D0%BD%D0%BE%D0%B2%D0%BD%D0%BE%D0%B9-%D1%83%D0%B4%D0%B0%D0%BB%D0%B5%D0%BD%D0%BD%D0%BE%D0%B9-%D0%B2%D0%B5%D1%82%D0%BA%D0%B8)\n    - [Я сделал изменения в неправильной ветке](#%D0%AF-%D1%81%D0%B4%D0%B5%D0%BB%D0%B0%D0%BB-%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F-%D0%B2-%D0%BD%D0%B5%D0%BF%D1%80%D0%B0%D0%B2%D0%B8%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9-%D0%B2%D0%B5%D1%82%D0%BA%D0%B5)\n  - [Перебазирование (rebase) и слияние (merge)](#%D0%9F%D0%B5%D1%80%D0%B5%D0%B1%D0%B0%D0%B7%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-rebase-%D0%B8-%D1%81%D0%BB%D0%B8%D1%8F%D0%BD%D0%B8%D0%B5-merge)\n    - [Я хочу отменить перебазирование/слияние](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D0%BE%D1%82%D0%BC%D0%B5%D0%BD%D0%B8%D1%82%D1%8C-%D0%BF%D0%B5%D1%80%D0%B5%D0%B1%D0%B0%D0%B7%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%D1%81%D0%BB%D0%B8%D1%8F%D0%BD%D0%B8%D0%B5)\n    - [Я сделал перебазирование, но я не хочу делать принудительный push](#%D0%AF-%D1%81%D0%B4%D0%B5%D0%BB%D0%B0%D0%BB-%D0%BF%D0%B5%D1%80%D0%B5%D0%B1%D0%B0%D0%B7%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D0%BD%D0%BE-%D1%8F-%D0%BD%D0%B5-%D1%85%D0%BE%D1%87%D1%83-%D0%B4%D0%B5%D0%BB%D0%B0%D1%82%D1%8C-%D0%BF%D1%80%D0%B8%D0%BD%D1%83%D0%B4%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D1%8B%D0%B9-push)\n    - [Я хочу объединить коммиты](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D0%BE%D0%B1%D1%8A%D0%B5%D0%B4%D0%B8%D0%BD%D0%B8%D1%82%D1%8C-%D0%BA%D0%BE%D0%BC%D0%BC%D0%B8%D1%82%D1%8B)\n      - [Безопасная стратегия слияния](#%D0%91%D0%B5%D0%B7%D0%BE%D0%BF%D0%B0%D1%81%D0%BD%D0%B0%D1%8F-%D1%81%D1%82%D1%80%D0%B0%D1%82%D0%B5%D0%B3%D0%B8%D1%8F-%D1%81%D0%BB%D0%B8%D1%8F%D0%BD%D0%B8%D1%8F)\n      - [Мне нужно слить ветку в единственный коммит](#%D0%9C%D0%BD%D0%B5-%D0%BD%D1%83%D0%B6%D0%BD%D0%BE-%D1%81%D0%BB%D0%B8%D1%82%D1%8C-%D0%B2%D0%B5%D1%82%D0%BA%D1%83-%D0%B2-%D0%B5%D0%B4%D0%B8%D0%BD%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D0%B9-%D0%BA%D0%BE%D0%BC%D0%BC%D0%B8%D1%82)\n      - [Я хочу объединить только неопубликованные коммиты](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D0%BE%D0%B1%D1%8A%D0%B5%D0%B4%D0%B8%D0%BD%D0%B8%D1%82%D1%8C-%D1%82%D0%BE%D0%BB%D1%8C%D0%BA%D0%BE-%D0%BD%D0%B5%D0%BE%D0%BF%D1%83%D0%B1%D0%BB%D0%B8%D0%BA%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B5-%D0%BA%D0%BE%D0%BC%D0%BC%D0%B8%D1%82%D1%8B)\n      - [Мне нужно прервать слияние](#%D0%9C%D0%BD%D0%B5-%D0%BD%D1%83%D0%B6%D0%BD%D0%BE-%D0%BF%D1%80%D0%B5%D1%80%D0%B2%D0%B0%D1%82%D1%8C-%D1%81%D0%BB%D0%B8%D1%8F%D0%BD%D0%B8%D0%B5)\n    - [Мне нужно обновить родительский коммит моей ветки](#%D0%9C%D0%BD%D0%B5-%D0%BD%D1%83%D0%B6%D0%BD%D0%BE-%D0%BE%D0%B1%D0%BD%D0%BE%D0%B2%D0%B8%D1%82%D1%8C-%D1%80%D0%BE%D0%B4%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D1%81%D0%BA%D0%B8%D0%B9-%D0%BA%D0%BE%D0%BC%D0%BC%D0%B8%D1%82-%D0%BC%D0%BE%D0%B5%D0%B9-%D0%B2%D0%B5%D1%82%D0%BA%D0%B8)\n    - [Проверить, что все коммиты ветви были слиты](#%D0%9F%D1%80%D0%BE%D0%B2%D0%B5%D1%80%D0%B8%D1%82%D1%8C-%D1%87%D1%82%D0%BE-%D0%B2%D1%81%D0%B5-%D0%BA%D0%BE%D0%BC%D0%BC%D0%B8%D1%82%D1%8B-%D0%B2%D0%B5%D1%82%D0%B2%D0%B8-%D0%B1%D1%8B%D0%BB%D0%B8-%D1%81%D0%BB%D0%B8%D1%82%D1%8B)\n    - [Возможные проблемы интерактивного перебазирования](#%D0%92%D0%BE%D0%B7%D0%BC%D0%BE%D0%B6%D0%BD%D1%8B%D0%B5-%D0%BF%D1%80%D0%BE%D0%B1%D0%BB%D0%B5%D0%BC%D1%8B-%D0%B8%D0%BD%D1%82%D0%B5%D1%80%D0%B0%D0%BA%D1%82%D0%B8%D0%B2%D0%BD%D0%BE%D0%B3%D0%BE-%D0%BF%D0%B5%D1%80%D0%B5%D0%B1%D0%B0%D0%B7%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F)\n      - [Экран перебазирования говорит 'noop'](#%D0%AD%D0%BA%D1%80%D0%B0%D0%BD-%D0%BF%D0%B5%D1%80%D0%B5%D0%B1%D0%B0%D0%B7%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F-%D0%B3%D0%BE%D0%B2%D0%BE%D1%80%D0%B8%D1%82-noop)\n      - [Здесь были конфликты](#%D0%97%D0%B4%D0%B5%D1%81%D1%8C-%D0%B1%D1%8B%D0%BB%D0%B8-%D0%BA%D0%BE%D0%BD%D1%84%D0%BB%D0%B8%D0%BA%D1%82%D1%8B)\n  - [Отложенные изменения (stash)](#%D0%9E%D1%82%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%BD%D1%8B%D0%B5-%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F-stash)\n    - [Отложить все правки](#%D0%9E%D1%82%D0%BB%D0%BE%D0%B6%D0%B8%D1%82%D1%8C-%D0%B2%D1%81%D0%B5-%D0%BF%D1%80%D0%B0%D0%B2%D0%BA%D0%B8)\n    - [Отложить заданные файлы](#%D0%9E%D1%82%D0%BB%D0%BE%D0%B6%D0%B8%D1%82%D1%8C-%D0%B7%D0%B0%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D0%B5-%D1%84%D0%B0%D0%B9%D0%BB%D1%8B)\n    - [Отложить с сообщением](#%D0%9E%D1%82%D0%BB%D0%BE%D0%B6%D0%B8%D1%82%D1%8C-%D1%81-%D1%81%D0%BE%D0%BE%D0%B1%D1%89%D0%B5%D0%BD%D0%B8%D0%B5%D0%BC)\n    - [Применить заданный stash из списка](#%D0%9F%D1%80%D0%B8%D0%BC%D0%B5%D0%BD%D0%B8%D1%82%D1%8C-%D0%B7%D0%B0%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9-stash-%D0%B8%D0%B7-%D1%81%D0%BF%D0%B8%D1%81%D0%BA%D0%B0)\n  - [Поиск](#%D0%9F%D0%BE%D0%B8%D1%81%D0%BA)\n    - [Я хочу найти строку в коммитах](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D0%BD%D0%B0%D0%B9%D1%82%D0%B8-%D1%81%D1%82%D1%80%D0%BE%D0%BA%D1%83-%D0%B2-%D0%BA%D0%BE%D0%BC%D0%BC%D0%B8%D1%82%D0%B0%D1%85)\n    - [Я хочу искать по автору или сохранившему изменения (committer)](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D0%B8%D1%81%D0%BA%D0%B0%D1%82%D1%8C-%D0%BF%D0%BE-%D0%B0%D0%B2%D1%82%D0%BE%D1%80%D1%83-%D0%B8%D0%BB%D0%B8-%D1%81%D0%BE%D1%85%D1%80%D0%B0%D0%BD%D0%B8%D0%B2%D1%88%D0%B5%D0%BC%D1%83-%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F-committer)\n    - [Я хочу получить список коммитов, содержащих заданный файл](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D0%BF%D0%BE%D0%BB%D1%83%D1%87%D0%B8%D1%82%D1%8C-%D1%81%D0%BF%D0%B8%D1%81%D0%BE%D0%BA-%D0%BA%D0%BE%D0%BC%D0%BC%D0%B8%D1%82%D0%BE%D0%B2-%D1%81%D0%BE%D0%B4%D0%B5%D1%80%D0%B6%D0%B0%D1%89%D0%B8%D1%85-%D0%B7%D0%B0%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9-%D1%84%D0%B0%D0%B9%D0%BB)\n    - [Я хочу посмотреть историю коммитов для отдельной функции](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D0%BF%D0%BE%D1%81%D0%BC%D0%BE%D1%82%D1%80%D0%B5%D1%82%D1%8C-%D0%B8%D1%81%D1%82%D0%BE%D1%80%D0%B8%D1%8E-%D0%BA%D0%BE%D0%BC%D0%BC%D0%B8%D1%82%D0%BE%D0%B2-%D0%B4%D0%BB%D1%8F-%D0%BE%D1%82%D0%B4%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9-%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8)\n    - [Найти метки для заданного коммита](#%D0%9D%D0%B0%D0%B9%D1%82%D0%B8-%D0%BC%D0%B5%D1%82%D0%BA%D0%B8-%D0%B4%D0%BB%D1%8F-%D0%B7%D0%B0%D0%B4%D0%B0%D0%BD%D0%BD%D0%BE%D0%B3%D0%BE-%D0%BA%D0%BE%D0%BC%D0%BC%D0%B8%D1%82%D0%B0)\n  - [Субмодули](#%D0%A1%D1%83%D0%B1%D0%BC%D0%BE%D0%B4%D1%83%D0%BB%D0%B8)\n    - [Клонировать все субмодули](#%D0%9A%D0%BB%D0%BE%D0%BD%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D1%82%D1%8C-%D0%B2%D1%81%D0%B5-%D1%81%D1%83%D0%B1%D0%BC%D0%BE%D0%B4%D1%83%D0%BB%D0%B8)\n    - [Удалить субмодуль](#%D0%A3%D0%B4%D0%B0%D0%BB%D0%B8%D1%82%D1%8C-%D1%81%D1%83%D0%B1%D0%BC%D0%BE%D0%B4%D1%83%D0%BB%D1%8C)\n  - [Разное](#%D0%A0%D0%B0%D0%B7%D0%BD%D0%BE%D0%B5)\n    - [Восстановить удаленный файл](#%D0%92%D0%BE%D1%81%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%82%D1%8C-%D1%83%D0%B4%D0%B0%D0%BB%D0%B5%D0%BD%D0%BD%D1%8B%D0%B9-%D1%84%D0%B0%D0%B9%D0%BB)\n    - [Удалить метку](#%D0%A3%D0%B4%D0%B0%D0%BB%D0%B8%D1%82%D1%8C-%D0%BC%D0%B5%D1%82%D0%BA%D1%83)\n    - [Восстановить удаленную метку](#%D0%92%D0%BE%D1%81%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%82%D1%8C-%D1%83%D0%B4%D0%B0%D0%BB%D0%B5%D0%BD%D0%BD%D1%83%D1%8E-%D0%BC%D0%B5%D1%82%D0%BA%D1%83)\n    - [Удаленный патч](#%D0%A3%D0%B4%D0%B0%D0%BB%D0%B5%D0%BD%D0%BD%D1%8B%D0%B9-%D0%BF%D0%B0%D1%82%D1%87)\n    - [Экспорт репозитория в Zip-файл](#%D0%AD%D0%BA%D1%81%D0%BF%D0%BE%D1%80%D1%82-%D1%80%D0%B5%D0%BF%D0%BE%D0%B7%D0%B8%D1%82%D0%BE%D1%80%D0%B8%D1%8F-%D0%B2-zip-%D1%84%D0%B0%D0%B9%D0%BB)\n    - [Как опубликовать ветку и метку, если они имеют одинаковые имена](#%D0%9A%D0%B0%D0%BA-%D0%BE%D0%BF%D1%83%D0%B1%D0%BB%D0%B8%D0%BA%D0%BE%D0%B2%D0%B0%D1%82%D1%8C-%D0%B2%D0%B5%D1%82%D0%BA%D1%83-%D0%B8-%D0%BC%D0%B5%D1%82%D0%BA%D1%83-%D0%B5%D1%81%D0%BB%D0%B8-%D0%BE%D0%BD%D0%B8-%D0%B8%D0%BC%D0%B5%D1%8E%D1%82-%D0%BE%D0%B4%D0%B8%D0%BD%D0%B0%D0%BA%D0%BE%D0%B2%D1%8B%D0%B5-%D0%B8%D0%BC%D0%B5%D0%BD%D0%B0)\n  - [Отслеживание файлов](#%D0%9E%D1%82%D1%81%D0%BB%D0%B5%D0%B6%D0%B8%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D1%84%D0%B0%D0%B9%D0%BB%D0%BE%D0%B2)\n    - [Я хочу изменить регистр в имени файла, не меняя содержимое файла](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D0%B8%D1%82%D1%8C-%D1%80%D0%B5%D0%B3%D0%B8%D1%81%D1%82%D1%80-%D0%B2-%D0%B8%D0%BC%D0%B5%D0%BD%D0%B8-%D1%84%D0%B0%D0%B9%D0%BB%D0%B0-%D0%BD%D0%B5-%D0%BC%D0%B5%D0%BD%D1%8F%D1%8F-%D1%81%D0%BE%D0%B4%D0%B5%D1%80%D0%B6%D0%B8%D0%BC%D0%BE%D0%B5-%D1%84%D0%B0%D0%B9%D0%BB%D0%B0)\n    - [Я хочу переписать локальные файлы при выполнении git pull](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D0%BF%D0%B5%D1%80%D0%B5%D0%BF%D0%B8%D1%81%D0%B0%D1%82%D1%8C-%D0%BB%D0%BE%D0%BA%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D0%B5-%D1%84%D0%B0%D0%B9%D0%BB%D1%8B-%D0%BF%D1%80%D0%B8-%D0%B2%D1%8B%D0%BF%D0%BE%D0%BB%D0%BD%D0%B5%D0%BD%D0%B8%D0%B8-git-pull)\n    - [Я хочу удалить файл из git, но оставить сам файл](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D1%83%D0%B4%D0%B0%D0%BB%D0%B8%D1%82%D1%8C-%D1%84%D0%B0%D0%B9%D0%BB-%D0%B8%D0%B7-git-%D0%BD%D0%BE-%D0%BE%D1%81%D1%82%D0%B0%D0%B2%D0%B8%D1%82%D1%8C-%D1%81%D0%B0%D0%BC-%D1%84%D0%B0%D0%B9%D0%BB)\n    - [Я хочу откатить файл до заданной ревизии](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D0%BE%D1%82%D0%BA%D0%B0%D1%82%D0%B8%D1%82%D1%8C-%D1%84%D0%B0%D0%B9%D0%BB-%D0%B4%D0%BE-%D0%B7%D0%B0%D0%B4%D0%B0%D0%BD%D0%BD%D0%BE%D0%B9-%D1%80%D0%B5%D0%B2%D0%B8%D0%B7%D0%B8%D0%B8)\n    - [Я хочу получить список изменений в заданном файле из разных коммитов или веток](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D0%BF%D0%BE%D0%BB%D1%83%D1%87%D0%B8%D1%82%D1%8C-%D1%81%D0%BF%D0%B8%D1%81%D0%BE%D0%BA-%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D0%B5%D0%BD%D0%B8%D0%B9-%D0%B2-%D0%B7%D0%B0%D0%B4%D0%B0%D0%BD%D0%BD%D0%BE%D0%BC-%D1%84%D0%B0%D0%B9%D0%BB%D0%B5-%D0%B8%D0%B7-%D1%80%D0%B0%D0%B7%D0%BD%D1%8B%D1%85-%D0%BA%D0%BE%D0%BC%D0%BC%D0%B8%D1%82%D0%BE%D0%B2-%D0%B8%D0%BB%D0%B8-%D0%B2%D0%B5%D1%82%D0%BE%D0%BA)\n    - [Я хочу, чтобы Git игнорировал изменения в определенном файле](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D1%87%D1%82%D0%BE%D0%B1%D1%8B-git-%D0%B8%D0%B3%D0%BD%D0%BE%D1%80%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BB-%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F-%D0%B2-%D0%BE%D0%BF%D1%80%D0%B5%D0%B4%D0%B5%D0%BB%D0%B5%D0%BD%D0%BD%D0%BE%D0%BC-%D1%84%D0%B0%D0%B9%D0%BB%D0%B5)\n  - [Отладка с помощью Git](#%D0%9E%D1%82%D0%BB%D0%B0%D0%B4%D0%BA%D0%B0-%D1%81-%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E-git)\n  - [Конфигурация](#%D0%9A%D0%BE%D0%BD%D1%84%D0%B8%D0%B3%D1%83%D1%80%D0%B0%D1%86%D0%B8%D1%8F)\n    - [Я хочу добавить псевдонимы для некоторых команд Git](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D0%B4%D0%BE%D0%B1%D0%B0%D0%B2%D0%B8%D1%82%D1%8C-%D0%BF%D1%81%D0%B5%D0%B2%D0%B4%D0%BE%D0%BD%D0%B8%D0%BC%D1%8B-%D0%B4%D0%BB%D1%8F-%D0%BD%D0%B5%D0%BA%D0%BE%D1%82%D0%BE%D1%80%D1%8B%D1%85-%D0%BA%D0%BE%D0%BC%D0%B0%D0%BD%D0%B4-git)\n    - [Я хочу добавить в свой репозиторий пустую папку](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D0%B4%D0%BE%D0%B1%D0%B0%D0%B2%D0%B8%D1%82%D1%8C-%D0%B2-%D1%81%D0%B2%D0%BE%D0%B9-%D1%80%D0%B5%D0%BF%D0%BE%D0%B7%D0%B8%D1%82%D0%BE%D1%80%D0%B8%D0%B9-%D0%BF%D1%83%D1%81%D1%82%D1%83%D1%8E-%D0%BF%D0%B0%D0%BF%D0%BA%D1%83)\n    - [Я хочу сохранить имя пользователя и пароль для репозитория](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D1%81%D0%BE%D1%85%D1%80%D0%B0%D0%BD%D0%B8%D1%82%D1%8C-%D0%B8%D0%BC%D1%8F-%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D1%8F-%D0%B8-%D0%BF%D0%B0%D1%80%D0%BE%D0%BB%D1%8C-%D0%B4%D0%BB%D1%8F-%D1%80%D0%B5%D0%BF%D0%BE%D0%B7%D0%B8%D1%82%D0%BE%D1%80%D0%B8%D1%8F)\n    - [Я хочу, чтобы Git игнорировал изменения разрешений и прав файлов](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D1%87%D1%82%D0%BE%D0%B1%D1%8B-git-%D0%B8%D0%B3%D0%BD%D0%BE%D1%80%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BB-%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F-%D1%80%D0%B0%D0%B7%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B9-%D0%B8-%D0%BF%D1%80%D0%B0%D0%B2-%D1%84%D0%B0%D0%B9%D0%BB%D0%BE%D0%B2)\n    - [Я хочу задать данные пользователя в глобальных настройках](#%D0%AF-%D1%85%D0%BE%D1%87%D1%83-%D0%B7%D0%B0%D0%B4%D0%B0%D1%82%D1%8C-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D0%B5-%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D1%8F-%D0%B2-%D0%B3%D0%BB%D0%BE%D0%B1%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D1%85-%D0%BD%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B0%D1%85)\n  - [Я не представляю что я сделал неправильно](#%D0%AF-%D0%BD%D0%B5-%D0%BF%D1%80%D0%B5%D0%B4%D1%81%D1%82%D0%B0%D0%B2%D0%BB%D1%8F%D1%8E-%D1%87%D1%82%D0%BE-%D1%8F-%D1%81%D0%B4%D0%B5%D0%BB%D0%B0%D0%BB-%D0%BD%D0%B5%D0%BF%D1%80%D0%B0%D0%B2%D0%B8%D0%BB%D1%8C%D0%BD%D0%BE)\n  - [Сокращения для команд Git](#%D0%A1%D0%BE%D0%BA%D1%80%D0%B0%D1%89%D0%B5%D0%BD%D0%B8%D1%8F-%D0%B4%D0%BB%D1%8F-%D0%BA%D0%BE%D0%BC%D0%B0%D0%BD%D0%B4-git)\n    - [Git Bash](#git-bash)\n    - [PowerShell в Windows](#powershell-%D0%B2-windows)\n- [Другие ресурсы](#%D0%94%D1%80%D1%83%D0%B3%D0%B8%D0%B5-%D1%80%D0%B5%D1%81%D1%83%D1%80%D1%81%D1%8B)\n  - [Книги](#%D0%9A%D0%BD%D0%B8%D0%B3%D0%B8)\n  - [Учебники](#%D0%A3%D1%87%D0%B5%D0%B1%D0%BD%D0%B8%D0%BA%D0%B8)\n  - [Скрипты и инструменты](#%D0%A1%D0%BA%D1%80%D0%B8%D0%BF%D1%82%D1%8B-%D0%B8-%D0%B8%D0%BD%D1%81%D1%82%D1%80%D1%83%D0%BC%D0%B5%D0%BD%D1%82%D1%8B)\n  - [Графические клиенты](#%D0%93%D1%80%D0%B0%D1%84%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D0%B5-%D0%BA%D0%BB%D0%B8%D0%B5%D0%BD%D1%82%D1%8B)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n## Репозитории\n\n### Я хочу создать локальный репозиторий\n\nЧтобы создать репозиторий Git в текущей папке:\n\n```sh\n(my-folder) $ git init\n```\n\n### Я хочу клонировать удаленный репозиторий\n\nЧтобы клонировать (копировать) удаленный репозиторий, скопируйте URL репозитория и запустите:\n\n```sh\n$ git clone [url]\n```\n\nGit сохранит копию в папке с названием репозитория. Убедитесь, что у Вас есть соединение с удаленным сервером, откуда Вы клонируете (в большинстве случаев это означает наличие выхода в Интернет).\n\nЧтобы клонировать в папку с произвольным именем:\n\n```sh\n$ git clone [url] name-of-new-folder\n```\n\n### Я неправильно задал удаленный репозиторий\n\nВот несколько возможных проблем:\n\nЕсли Вы склонировали неправильный репозиторий, то просто удалите появившуюся папку и склонируйте правильный репозиторий.\n\nЕсли Вы неправильно настроили origin для существующего локального репозиторий, то измените URL-адрес origin на правильный с помощью:\n\n```sh\n$ git remote set-url origin [правильный url]\n```\n\nСм. [подробнее на StackOverflow](https://stackoverflow.com/questions/2432764/how-to-change-the-uri-url-for-a-remote-git-repository#2432799).\n\n\n### Я хочу добавить код в чужой репозиторий\n\nGit не разрешает добавлять код в чужой репозиторий без соответствующих прав доступа. Так же, как и GitHub, который, вообще говоря, не является самим Git-ом, а скорее хостингом для репозиториев Git. Тем не менее, вы можете предложить код посредством патчей или, на GitHub, посредством форков (ответвлений) и пулл-реквестов (запросов на слияние).\n\nСначала немного о форках. Форк - это копия репозитория. Эта операция не имеет прямого отношения к Git, это общая операция на GitHub, Bitbucket, GitLab и на других хостингах репозиториев Git. Вы можете сделать форк с помощью веб-интерфейса.\n\n#### Предложение кода с помощью пулл-реквестов\n\nПосле создания форка вам нужно склонировать репозиторий на свой компьютер. Вы можете сделать мелкие правки прямо на GitHub без клонирования, но это не \"Правила полёта на GitHub\", так что рассмотрим, как это сделать у себя на компьютере.\n\n```sh\n# если вы используете SSH\n$ git clone git@github.com:k88hudson/git-flight-rules.git\n\n# если вы используете HTTPS\n$ git clone https://github.com/k88hudson/git-flight-rules.git\n```\n\nЕсли перейти в появившийся каталог и ввести команду `git remote`, то напечатается список ссылок на удаленные репозитории. Обычно будет единственная ссылка `origin`, которая будет указывать на `k88hudson/git-flight-rules`. Ещё вам понадобится ссылка на ваш форк.\n\nСледуя общепринятым соглашениям, название `origin` используется для вашего собственного репозитория, а `upstream` - для исходного репозитория, с которого вы сделали форк. Так что переименуем `origin` в `upstream`\n\n```sh\n$ git remote rename origin upstream\n```\n\nВместо этого можно использовать `git remote set-url`, но это дольше и требует больше действий.\n\nТеперь настроим удаленную ссылку на ваш собственный репозиторий.\n\n```sh\n$ git remote add origin git@github.com:YourName/git-flight-rules.git\n```\n\nОбратите внимание, что у вас два удаленных репозитория.\n\n- `origin` ссылается на ваш собственный репозиторий.\n- `upstream` ссылается на исходный репозиторий.\n\nРепозиторий origin доступен для чтения и записи, тогда как upstream доступен только для чтения.\n\nКогда вы сделаете изменения, которые хотели, отправьте свои изменения (которые обычно делаются в отдельной ветке) в репозиторий `origin`. Если вы делаете изменения в отдельной ветке, то удобно пользоваться опцией `--set-upstream`, чтобы в будущем при отправке данной локальной ветки не приходилось каждый раз указывать удаленную ветку. Например:\n\n```sh\n$ (feature/my-feature) git push --set-upstream origin feature/my-feature\n```\n\nGit не располагает командами для создания пулл-реквестов (хотя есть внешние инструменты вроде [hub](http://github.com/github/hub)). Так что, когда подготовите необходимые изменения, открывайте GitHub (или другой сервер Git) и создавайте пулл-реквест. Обратите внимание, что сервер автоматически связывает исходный репозиторий и форк.\n\nПосле этого не забудьте добавить описание предлагаемых изменений.\n\n#### Мне нужно обновить свой форк последними изменениями из исходного репозитория\n\nСо временем репозиторий `upstream` может обновиться, и эти обновления нужно внести в ваш репозиторий `origin`. Не забывайте, что другие люди тоже вносят свои изменения. Предположим, вы находитесь на ветке для своей фичи и вам нужно её обновить согласно последним изменениям исходного репозитория.\n\nВозможно, вы уже настроили ссылку на исходный удаленный репозиторий. Если нет, тогда сделайте это сейчас. Обычно исходный удаленный репозиторий называют `upstream`:\n\n```sh\n$ (main) git remote add upstream <link-to-original-repository>\n# $ (main) git remote add upstream git@github.com:k88hudson/git-flight-rules.git\n```\n\nТеперь вы можете получить последние обновления из upstream.\n\n```sh\n$ (main) git fetch upstream\n$ (main) git merge upstream/main\n\n# или одной командой\n$ (main) git pull upstream main\n```\n\n## Редактирование коммитов\n\n<a name=\"diff-last\"></a>\n### Что я только что сохранил?\n\nДопустим, Вы не глядя сохранили изменения с помощью `git commit -a` и теперь не уверены что именно сохранили. В таком случае Вы можете просмотреть последний коммит в HEAD с помощью:\n\n```sh\n(main)$ git show\n```\n\nИли\n\n```sh\n$ git log -n1 -p\n```\n\nЕсли Вы хотите просмотреть файл из определенного коммита, Вы можете сделать так (`<commitid>` - нужный Вам коммит):\n\n```sh\n$ git show <commitid>:filename\n```\n\n<a name=\"wrong-thing-in-commit-message\"></a>\n### Я неправильно написал сообщение коммита\n\nЕсли Вы неправильно сохранили коммит, но еще не сделали `push`, то для исправления сообщения коммита сделайте следующее:\n\n```sh\n$ git commit --amend --only\n```\n\nЭто откроет текстовый редактор по-умолчанию, в котором Вы сможете исправить сообщение. С другой стороны Вы можете сделать это одной командой:\n\n```sh\n$ git commit --amend --only -m 'xxxxxxx'\n```\n\nЕсли Вы уже сделали `push`, то Вы по-прежнему можете исправить коммит, но после этого придется делать `push` с принудительной перезаписью, что не рекомендуется.\n\n<a name=\"commit-wrong-author\"></a>\n### Я сделал коммит с неправильным именем автора и адресом электронной почты\n\nЕсли это один коммит, то исправьте его с помощью `amend`\n\n```sh\n$ git commit --amend --no-edit --author \"New Authorname <authoremail@mydomain.com>\"\n```\n\nИли Вы можете сконфигурировать глобальные настройки автора `git config --global author.(name|email)`, а затем выполнить\n\n```sh\n$ git commit --amend --reset-author --no-edit\n```\n\nЕсли Вам нужно изменить всю историю, то смотрите документацию для `git filter-branch`.\n\n### Я хочу удалить файл из предыдущего коммита\n\nЧтобы удалить изменения файла из предыдущего коммита, сделайте следующее:\n\n```sh\n$ git checkout HEAD^ myfile\n$ git add myfile\n$ git commit --amend --no-edit\n```\n\nКогда в коммит был добавлен новый файл и Вы хотите его удалить (только из Git), выполните:\n\n```sh\n$ git rm --cached myfile\n$ git commit --amend --no-edit\n```\n\nЭто особенно полезно, когда у Вас открытый патч, а Вы сохранили ненужный файл и теперь нужно сделать принудительный `push` для обновления патча в удаленном репозитории. Опция `--no-edit` оставляет прежнее сообщение коммита без изменений.\n\n<a name=\"delete-pushed-commit\"></a>\n### Я хочу удалить последний коммит\n\nЕсли хотите удалить опубликованные коммиты, воспользуйтесь приведенным ниже приемом. Однако, это бесповоротно изменит у Вас историю Git, а также испортит историю Git у любого, что уже стянул (pull) изменения из репозитория. Короче говоря, никогда так не делайте, если не уверены.\n\n```sh\n$ git reset HEAD^ --hard\n$ git push --force-with-lease [remote] [branch]\n```\n\nЕсли Вы еще не опубликовали коммит, то просто сбросьте ветку в состояние перед Вашим последним коммитом (подготовленные изменения не пропадут):\n\n```\n(my-branch)$ git reset --soft HEAD^\n```\n\nЭто работает, если Вы еще не сделали `push`. Если Вы уже сделали `push`, то единственный по-настоящему безопасный способ это `git revert SHAofBadCommit`. Это создаст новый коммит, который отменит все изменения предыдущего коммита. Или, если ветка, в которую вы делаете `push` безопасна для перезаписи (т.е. не предполагается, другие разработчики будут стягивать из нее изменения), то просто используйте `git push --force-with-lease`. Подробнее см. [в этом пункте выше](#delete-pushed-commit).\n\n<a name=\"delete-any-commit\"></a>\n### Удалить произвольный коммит\n\nЗдесь уместны те же предупреждения, что и в пункте выше. По возможности, никогда так не делайте.\n\n```sh\n$ git rebase --onto SHA1_OF_BAD_COMMIT^ SHA1_OF_BAD_COMMIT\n$ git push --force-with-lease [remote] [branch]\n```\n\nИли сделайте [интерактивное перебазирование](#interactive-rebase) и удалите строки ненужных коммитов.\n\n<a name=\"force-push\"></a>\n### Я пытаюсь опубликовать исправленный коммит, но получаю сообщение об ошибке\n\n```sh\nTo https://github.com/yourusername/repo.git\n! [rejected]        mybranch -> mybranch (non-fast-forward)\nerror: failed to push some refs to 'https://github.com/tanay1337/webmaker.org.git'\nhint: Updates were rejected because the tip of your current branch is behind\nhint: its remote counterpart. Integrate the remote changes (e.g.\nhint: 'git pull ...') before pushing again.\nhint: See the 'Note about fast-forwards' in 'git push --help' for details.\n```\n\nНапомним, что подобно перебазированию (см. ниже), исправление коммита (amend) **заменяет старый коммит новым**, поэтому Вы должны делать принудительный `push` (`--force-with-lease`) Ваших изменений, если хотите заменить уже опубликованные на удаленном репозитории коммиты. Будьте осторожны, когда так делаете – *всегда* проверяйте с какой веткой Вы проводите эти действия!\n\n```sh\n(my-branch)$ git push origin mybranch --force-with-lease\n```\n\nВ общем, **избегайте делать принудительный push**. Лучше создать и опубликовать еще один коммит, чем переписывать измененные коммиты, т.к. это приведет к конфликтам истории у других разработчиков, которые работают с этой или дочерними ветками. `--force-with-lease` по-прежнему выдаст ошибку, если кто-то одновременно с Вами работает с данной веткой и Ваш принудительный push переписал бы чужие изменения.\n\nЕсли Вы *абсолютно* уверены, что никто кроме Вас не работает с данной веткой или Вы хотите обновить вершину ветви в любом случае, то используйте `--force` (`-f`), но вообще этого следует избегать.\n\n<a name=\"undo-git-reset-hard\"></a>\n### Я случайно сделал жесткий сброс (--hard) и теперь хочу вернуть свои изменения\n\nЕсли Вы случайно сделали `git reset --hard`, то вы можете вернуть назад коммиты, т.к. Git несколько дней хранит все действия в журнале.\n\nЗамечание: Это относится только если ваша работа была сохранена, т.е. Вы сделали коммит или stash. `git reset --hard` *удалит* несохраненные изменения, так что пользуйтесь им с осторожностью. (Безопасная опция это `git reset --keep`.)\n\n```sh\n(main)$ git reflog\n```\n\nВы увидете список Ваших предыдущих коммитов и коммит для сброса. Выберите SHA коммита, который хотите вернуть и снова сделайте сброс:\n\n```sh\n(main)$ git reset --hard SHA1234\n```\n\nИ Вы сможете продолжить работу.\n\n<a name=\"undo-a-commit-merge\"></a>\n### Я случайно опубликовал ненужное слияние\n\nЕсли Вы случайно сделали слияние в основную ветку разработки до того, как были сделаны все необходимые изменения, Вы по-прежнему можете отменить слияние. Но есть одна загвоздка: Коммит слияния имеет более одного родителя (обычно два).\n\nКоманда для решения этой проблемы\n```sh\n(feature-branch)$ git revert -m 1 <commit>\n```\nгде опция -m 1 говорит выбрать родителя номер 1 (ветка, в которую было сделано слияние) в качестве родителя для отката.\n\nЗаметка: номер родителя - это не идентификатор коммита. Допустим, коммит слияния имеет строчку `Merge: 8e2ce2d 86ac2e7`. Номер родителя - это порядковый номер (отсчет с 1) нужного родителя в этой строчке, первый идентификатор - номер 1, второй - номер 2 и т.д.\n\n<a name=\"undo-sensitive-commit-push\"></a>\n### Я случайно закоммитил и опубликовал файлы с конфиденциальными данными\n\nЕсли Вы случайно опубликовали файлы, содержащие конфиденциальные данные (пароли, ключи и пр.), Вы можете изменить последний коммит с помощью amend. Помните, что как только Вы опубликовали коммит, то Вы должны считать всё его содержание скомпрометированным. С помощью дальнейших шагов можно удалить конфиденциальную информацию из публичного репозиторий или из Вашей локальной копии, вы **не сможете** удалить свою конфиденциальную информацию у людей, которые могли успеть скопировать себе её. Если Вы закоммитили пароль, то **незамедлительно поменяйте его**. Если Вы закоммитили ключ, то **незамедлительно сгенерируйте новый**. Изменения опубликованного коммита недостаточно, потому что кто-нибудь мог скопировать исходный коммит до того, как Вы успели его исправить.\n\nКак только удалите конфиденциальные данные из файла, запустите\n```sh\n(feature-branch)$ git add edited_file\n(feature-branch)$ git commit --amend --no-edit\n(feature-branch)$ git push --force-with-lease origin [branch]\n```\n\nЕсли Вы хотите удалить файл целиком, но оставить его в локальной копии, то запустите\n```sh\n(feature-branch)$ git rm --cached sensitive_file\necho sensitive_file >> .gitignore\n(feature-branch)$ git add .gitignore\n(feature-branch)$ git commit --amend --no-edit\n(feature-branch)$ git push --force-with-lease origin [branch]\n```\nДругим способом хранения конфиденциальных данных является хранение в переменных окружения.\n\nЕсли Вы хотите удалить файл целиком и не оставлять его в локальной копии, то запустите\n```sh\n(feature-branch)$ git rm sensitive_file\n(feature-branch)$ git commit --amend --no-edit\n(feature-branch)$ git push --force-with-lease origin [branch]\n```\n\nЕсли Вы успели сделать другие коммиты после коммита с конфиденциальными данными, то Вам нужно использовать rebase.\n\n<a name=\"remove-large-file-in-repo-history\"></a>\n### Я хочу удалить большой файл из истории репозитория\n\nЕсли вы хотите удалить пароль или другую конфиденциальную информацию, то вместо этого смотрите [Я случайно закоммитил и опубликовал файлы с конфиденциальными данными](#undo-sensitive-commit-push).\n\nДаже если вы удалите большие или ненужные файлы из последнего коммита, они останутся в истоии Git, в подкаталоге `.git` вашего репозитория и `git clone` будет загружать ненужные файлы.\n\nДействия, описанные в этой части руководства требуют принудительной перезаписи истории репозитория Git, так что, если вы сотрудничаете с удаленными разработчиками, что сначала убедитесь, что они опубликовали на сервере все свои локальные изменения.\n\n Есть два способа переписывания истории: встроенная команда `git-filter-branch` и сторонняя программа [`bfg-repo-cleaner`](https://rtyley.github.io/bfg-repo-cleaner/). `bfg` значительно понятнее в использовании и быстрее по производительности, но её нужно устанавливать отдельно и она требует Java. Мы опишем оба этих способа. Финальный шаг - это принудительный push ваших изменений, который мы обсудим отдельно, поскольку, в отличие от обычного принудительного push, он приводит к масштабной безвозвратной перезаписи истории.\n\n#### Рекомендуемый способ: Использование bfg\n\nИспользование bfg-repo-cleaner требует наличия Java. Скачайте bfg jar-файл по ссылке [здесь](https://rtyley.github.io/bfg-repo-cleaner/). В наших примерах будет использоваться `bfg.jar`, а загруженный вами файл будет содержать в названии номер версии, например, `bfg-1.13.0.jar`.\n\nЧтобы удалить определенный файл:\n```sh\n(main)$ git rm path/to/filetoremove\n(main)$ git commit -m \"Commit removing filetoremove\"\n(main)$ java -jar ~/Downloads/bfg.jar --delete-files filetoremove\n```\nЗаметьте, что в bfg вы должны использовать имя файла без пути, даже если файл находится в подкаталоге.\n\nТакже вы можете пользоваться шаблонами имен:\n```sh\n(main)$ git rm *.jpg\n(main)$ git commit -m \"Commit removing *.jpg\"\n(main)$ java -jar ~/Downloads/bfg.jar --delete-files *.jpg\n```\n\nПри использовании bfg, файлы, существующие в вашем последнем коммите не будут затронуты. Например, если в вашем репозитории было много больших .tga файлов, а потом вы удалили несколько из них, то bfg не тронет файлы, которые присутствуют в последнем коммите.\n\nЗаметьте, что если вы переименовали файл в коммите, например, если он сначала назывался `LargeFileFirstName.mp4` и коммит переименовал его в `LargeFileSecondName.mp4`, то запуск `java -jar ~/Downloads/bfg.jar --delete-files LargeFileSecondName.mp4` не удалит его из истории Git. В таком случае запустите команду `--delete-files` с обоими именами или с шаблоном имен.\n\n#### Встроенный способ: Использование git-filter-branch\n\nКоманду `git-filter-branch` сложнее использовать и она имеет меньше возможностей, но вы можете ей воспользоваться, если не хотите пользоваться `bfg`.\n\nВ приведенной ниже команде замените `filepattern` на требуемое имя или шаблон, например, `*.jpg`. Эта команда удалит файлы, подходящие под заданный шаблон из истории всех ветвей.\n\n```sh\n(main)$ git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch filepattern' --prune-empty --tag-name-filter cat -- --all\n```\n\nПояснения:\n\n`--tag-name-filter cat` - это неуклюжий, но в то же время самый простой способ применить исходные метки к новым коммитам с помощью команды cat.\n\n`--prune-empty` удаляет все коммиты, которые теперь стали пустыми.\n\n#### Финальный шаг: Публикация измененной истории репозитория\n\nКак только вы удалили файлы, которые хотели, внимально проверьте, что ничего не сломали в репозитории - если сломали, то проще всего склонировать ваш репозиторий и начать снова.\nДля завершения вы можете опционально запустить сборщик мусора Git, чтобы минимизировать размер локальной папки .git folder size, а после этого сделать принудительный push.\n```sh\n(main)$ git reflog expire --expire=now --all && git gc --prune=now --aggressive\n(main)$ git push origin --force --tags\n```\n\n После того, как вы переписали всю историю репозитория, операция `git push` может оказаться слишком большой и вернет ошибку `“The remote end hung up unexpectedly” (Удаленный хост неожиданно прервал соединение)`. Если это произошло, то попробуйте увеличить размер буфера передачи:\n```sh\n(main)$ git config http.postBuffer 524288000\n(main)$ git push --force\n```\n\nЕсли это не работает, то вам придется делать push частями. В команде ниже пробуйте увеличивать `<number>` пока push не сработает.\n```sh\n(main)$ git push -u origin HEAD~<number>:refs/head/main --force\n```\nПосле того как только команда push сработала в первый раз, постепенно уменьшайте `<number>`, пока не сработает обычная `git push`.\n\n<a name=\"change-content-of-commit-not-my-last\"></a>\n### Мне нужно изменить содержимое коммита, который не является последним\n\nПусть Вы сделали несколько (например, три) коммитов и после этого поняли, что упустили что-то, что по смыслу относится к первому из этих трёх коммитов. Вы могли бы сделать новый коммит, содержащий эти изменения, и тогда у Вас была бы чистая кодовая база, но Ваши коммиты не были бы атомарными (т.е. связанные изменения не содержались бы в едином коммите). В такой ситуации Вы бы хотели изменить коммит, к которому относятся эти изменения, а следующие коммиты оставить как есть. В таком случае Вас может спасти `git rebase`.\n\nРассмотрим ситуацию, когда Вы хотите изменить третий с конца коммит.\n\n```sh\n(your-branch)$ git rebase -i HEAD~4\n```\n\nзапустит интерактивный режим rebase, что позволит Вам отредактировать любые из Ваших последних трёх коммитов. Появится текстовый редактор с подобным содержанием:\n\n```sh\npick 9e1d264 The third last commit\npick 4b6e19a The second to last commit\npick f4037ec The last commit\n```\n\nкоторое Вам нужно изменить так:\n\n```sh\nedit 9e1d264 The third last commit\npick 4b6e19a The second to last commit\npick f4037ec The last commit\n```\n\nЭто говорит rebase, что Вы хотите изменить третий с конца коммит, а другие два оставить как есть. Теперь сохраните и закройте редактор. После этого Git начнет процедуру rebase. Он остановится на коммите, который Вы пометили для изменений, давая Вам возможность изменить этот коммит. Теперь Вы можете доделать то, что забыли первоначально. Отредактируйте и подготовьте изменения. После этого запустите\n\n```sh\n(your-branch)$ git commit --amend\n```\n\nэто заставит Git пересоздать коммит, но оставить сообщение коммита прежним. После этого тяжелая часть работы завершена.\n\n```sh\n(your-branch)$ git rebase --continue\n```\n\nсделает оставшуюся работу за Вас.\n\n## Подготовка изменений (staging)\n\n<a name=\"add-staged-changes-to-previous-commit\"></a>\n### Мне нужно добавить подготовленные изменения в предыдущий коммит\n\n```sh\n(my-branch*)$ git commit --amend\n```\n\nЕсли Вы не хотите менять сообщение коммита, скажите git использовать прежнее сообщение:\n\n```sh\n(my-branch*)$ git commit --amend -C HEAD\n```\n\n\n<a name=\"commit-partial-new-file\"></a>\n### Я хочу подготовить только часть файла, а не весь файл целиком\n\nОбычно, если хотите подготовить часть файл, Вы запускаете:\n\n```sh\n$ git add --patch filename.x\n```\n\n`-p` - сокращение для `--patch`. Это откроет интерактивный режим. Вы сможете разбить коммит с помощью опции `s`, однако, если файл новый, то у Вас не будет такой возможности. При добавлении нового файла делайте так:\n\n```sh\n$ git add -N filename.x\n```\n\nЗатем используйте опцию `e` для ручного выбора строк. Запустив `git diff --cached` или\n`git diff --staged`, Вы увидите какие строки вы подготовили по-сравнению с тем, что сохранено в рабочей копии.\n\n<a name=\"stage-in-two-commits\"></a>\n### Я хочу добавить изменения одного файла в два разных коммита\n\n`git add` добавляет в коммит весь файл целиком. `git add -p` позволяет интерактивно выбрать изменения, которые Вы хотите добавить.\n\n<a name=\"selective-unstage-edits\"></a>\n### Я подготовил слишком много правок и теперь хочу разделить их на несколько отдельных коммитов\n\n`git reset -p` откроет интерактивный диалог сброса.  Это похоже на `git add -p`, за исключением того, что выбор \"yes\" уберёт правку из готовящегося коммита.\n\n<a name=\"unstaging-edits-and-staging-the-unstaged\"></a>\n### Я хочу подготовить свои неподготовленные правки и убрать из подготовки то, что уже подготовлено\n\nЭто сложно. Лучшее, что я смог придумать это отложить (stash) неподготовленные изменения. Затем сделать сброс. После этого вернуть отложенные изменения и добавить их.\n\n```sh\n$ git stash -k\n$ git reset --hard\n$ git stash pop\n$ git add -A\n```\n\n## Неподготовленные правки\n\n<a name=\"move-unstaged-edits-to-new-branch\"></a>\n### Я хочу переместить мои неподготовленные правки в новую ветку\n\n```sh\n$ git checkout -b my-branch\n```\n\n<a name=\"move-unstaged-edits-to-old-branch\"></a>\n### Я хочу переместить неподготовленные правки в другую существующую ветку\n\n```sh\n$ git stash\n$ git checkout my-branch\n$ git stash pop\n```\n\n<a name=\"discard-local-uncommitted-changes\"></a>\n### Я хочу отменить мои локальные несохраненные изменения (подготовленные и неподготовленные)\n\nЕсли Вы хотите отменить все подготовленные и неподготовленные изменения, то можете сделать так:\n\n```sh\n(my-branch)$ git reset --hard\n# or\n(main)$ git checkout -f\n```\n\nЭто уберет из индекса все подготовленные изменения:\n\n```sh\n$ git reset\n```\n\nЭто удалит все локальные изменения, которые не были сохранены или добавлены в индекс (нужно запускать из корня репозитория):\n\n```sh\n$ git checkout .\n```\n\nВы также можете отменить несохраненные изменения в определенном файле или папке:\n\n```sh\n$ git checkout [some_dir|file.txt]\n```\n\nЕще один способ отменить все несохраненные изменения (длиннее, зато работает в любой папке):\n\n```sh\n$ git reset --hard HEAD\n```\n\nЭто удалит все локальные неотслеживаемые файлы, так что останутся только отслеживаемые:\n\n```sh\n$ git clean -fd\n```\n\n`-x` удалит также и игнорируемые файлы.\n\n### Я хочу отменить некоторые неподготовленные изменения\n\nКогда Вы хотите избавиться от некоторых, но не всех изменений в Вашей рабочей копии.\n\nСделайте checkout ненужных изменений, оставив нужные.\n\n```sh\n$ git checkout -p\n# Отвечайте `y` для всех фрагментов, которые Вы хотите выбросить\n```\n\nДругим подходом является использование stash. Отложите все хорошие изменения, сбросьте рабочую копию и верните отложенные хорошие изменения.\n\n```sh\n$ git stash -p\n# Выберите фрагменты, которые Вы хотите сохранить\n$ git reset --hard\n$ git stash pop\n```\n\nВ качестве альтернативы, отложите ненужные изменения, а затем выбросьте их.\n\n```sh\n$ git stash -p\n# Выберите фрагменты, которые Вы не хотите сохранять\n$ git stash drop\n```\n\n### Я хочу отбросить неподготовленные изменения в некоторых файлах\n\nКогда Вы хотите убрать изменения какого-то файла в Вашей рабочей копии.\n\n```sh\n$ git checkout myFile\n```\n\nЧтобы убрать изменения в нескольких файлах, перечислите их имена.\n\n```sh\n$ git checkout myFirstFile mySecondFile\n```\n\n### Я хочу убрать все неподготовленные локальные изменения\n\nКогда Вы хотите убрать все неподготовленные локальные изменения\n\n```sh\n$ git checkout .\n```\n<a name=\"discard-all-untracked-files\"></a>\n### Я хочу удалить все неотслеживаемые файлы\n\nКогда Вы хотите удалить все неотслеживаемые файлы\n\n```sh\n$ git clean -f\n```\n\n<a name=\"unstage-specific-staged-file\"></a>\n### Я хочу убрать заданный файл из подготовленного\n\nИногда один или несколько неотслеживаемых файлов ненароком оказываются в подготовленном. Чтобы убрать их из подготовленного:\n\n```sh\n$ git reset -- <filename>\n```\n\nЭто уберёт файл из подготовленного и он снова будет выглядеть как неотслеживаемый.\n\n## Ветки\n\n### Я хочу получить список всех веток\n\nСписок локальных веток\n\n```sh\n$ git branch\n```\n\nСписок удаленных веток\n\n```sh\n$ git branch -r\n```\n\nСписок всех веток (локальных и удаленных)\n\n```sh\n$ git branch -a\n```\n\n<a name=\"create-branch-from-commit\"></a>\n### Создать ветку на определенном коммите\n```sh\n$ git checkout -b <branch> <SHA1_OF_COMMIT>\n```\n\n<a name=\"pull-wrong-branch\"></a>\n### Я стянул изменения (pull) из неправильной ветки или в неправильную ветку\n\nЭто очередная возможность воспользоваться `git reflog`, чтобы посмотреть куда указывала ваша HEAD перед неправильным pull.\n\n```sh\n(main)$ git reflog\nab7555f HEAD@{0}: pull origin wrong-branch: Fast-forward\nc5bc55a HEAD@{1}: checkout: checkout message goes here\n```\n\nПросто сбросьте ветку обратно на требуемый коммит:\n\n```sh\n$ git reset --hard c5bc55a\n```\n\nГотово.\n\n<a name=\"discard-local-commits\"></a>\n### Я хочу отменить локальные коммиты, чтобы моя ветка стала такой же как на сервере\n\nПодтвердите, что не хотите отправлять изменения на сервер.\n\n`git status` покажет на сколько коммитов Вы опережаете источник:\n\n```sh\n(my-branch)$ git status\n# On branch my-branch\n# Your branch is ahead of 'origin/my-branch' by 2 commits.\n#   (use \"git push\" to publish your local commits)\n#\n```\n\nОдин из способов сбросить до источника (чтобы иметь то же, что и в удаленном репозитории):\n\n```sh\n(my-branch)$ git reset --hard origin/my-branch\n```\n\n<a name=\"commit-wrong-branch\"></a>\n### Я сохранил коммит в ветку main вместо новой ветки\n\nСоздайте новую ветку, оставаясь на main:\n\n```sh\n(main)$ git branch my-branch\n```\n\nСбросьте ветку main к предыдущему коммиту:\n\n```sh\n(main)$ git reset --hard HEAD^\n```\n\n`HEAD^` - это сокращение для `HEAD^1`. Это подставляет первого предка `HEAD`, подобно этому `HEAD^2` подставляет второго предка коммита (слияния могут иметь 2 предков).\n\nЗаметьте, что `HEAD^2` это **не** то же самое, что `HEAD~2` (для подробностей см. [эту ссылку](http://www.paulboxley.com/blog/2011/06/git-caret-and-tilde)).\n\nЕсли не хотите использовать `HEAD^`, то найдите хэш коммита, на который Вы хотите установить ветку (`git log` может помочь в этом). Затем сделайте сброс к этому хэшу. С помощью `git push` удостоверьтесь, что эти изменения отражены в удаленном репозитории.\n\nК примеру, ветка main обязана находится на коммите с хэшем `a13b85e`:\n\n```sh\n(main)$ git reset --hard a13b85e\nHEAD is now at a13b85e\n```\n\nПерейти на новую ветку для продолжения работы:\n\n```sh\n(main)$ git checkout my-branch\n```\n\n<a name=\"keep-whole-file\"></a>\n### Я хочу сохранить файл целиком из другого ref-ish\n\nСкажем, у Вас рабочий spike (см. заметку) на сотни изменений. Всё работает. Теперь Вы сохраняете эту работу в другую ветку:\n\n```sh\n(solution)$ git add -A && git commit -m \"Добавлены все изменения из этого рывка в один большой коммит.\"\n```\n\nКогда Вы хотите поместить его в ветку (например `feature` или `develop`), Вы хотите сохранять по целым файлам. А также Вы хотите разбить большой коммит на несколько небольших.\n\nСкажем, Вы имеете:\n\n- ветку `solution` с решением к Вашему spike. На один коммит впереди `develop`.\n- ветку `develop`, куда Вы хотите добавить Ваши изменения.\n\nВы можете выполнить это, перенеся содержимое файла в Вашу ветку:\n\n```sh\n(develop)$ git checkout solution -- file1.txt\n```\n\nЭто скопирует содержимое данного файла из ветки `solution` в ветку `develop`:\n\n```sh\n# On branch develop\n# Your branch is up-to-date with 'origin/develop'.\n# Changes to be committed:\n#  (use \"git reset HEAD <file>...\" to unstage)\n#\n#        modified:   file1.txt\n```\n\nТеперь сделайте коммит как обычно.\n\nЗаметка: Spike-решения делаются для анализа или решения проблемы. Эти решения используют, чтобы оценить проблему, и отбрасывают сразу же, как только все получают ясное представление о проблеме. ~ [Wikipedia](https://en.wikipedia.org/wiki/Extreme_programming_practices).\n\n<a name=\"cherry-pick\"></a>\n### Я сделал несколько коммитов в одной ветке, а нужно было сохранять их в разных ветках\n\nСкажем, Вы в ветке main. Запустив `git log`, Вы увидите, что сделали два коммита:\n\n```sh\n(main)$ git log\n\ncommit e3851e817c451cc36f2e6f3049db528415e3c114\nAuthor: Alex Lee <alexlee@example.com>\nDate:   Tue Jul 22 15:39:27 2014 -0400\n\n    Bug #21 - Added CSRF protection\n\ncommit 5ea51731d150f7ddc4a365437931cd8be3bf3131\nAuthor: Alex Lee <alexlee@example.com>\nDate:   Tue Jul 22 15:39:12 2014 -0400\n\n    Bug #14 - Fixed spacing on title\n\ncommit a13b85e984171c6e2a1729bb061994525f626d14\nAuthor: Aki Rose <akirose@example.com>\nDate:   Tue Jul 21 01:12:48 2014 -0400\n\n    First commit\n```\n\nОбратим внимание на ссылки на каждый баг (`e3851e8` для #21, `5ea5173` для #14).\n\nВо-первых, сбросим ветку main на правильный коммит (`a13b85e`):\n\n```sh\n(main)$ git reset --hard a13b85e\nHEAD is now at a13b85e\n```\n\nТеперь, мы может создать новую ветку для бага #21:\n\n```sh\n(main)$ git checkout -b 21\n(21)$\n```\n\nТеперь сделаем *cherry-pick* коммита для бага #21 на верх нашей ветки. Это значит, что мы помещаем этот и только этот коммит напрямую на вершину ветки, какой бы она ни была.\n\n```sh\n(21)$ git cherry-pick e3851e8\n```\n\nНа этом этапе есть вероятность конфликтов. О том как разрешить конфликты см. в главе [**Здесь были конфликты**](#merge-conflict) в [разделе интерактивное перебазирование выше](#interactive-rebase).\n\nТеперь давайте создадим новую ветку для бага #14, которая также основана на main\n\n```sh\n(21)$ git checkout main\n(main)$ git checkout -b 14\n(14)$\n```\n\nИ наконец, сделаем cherry-pick коммита для бага #14:\n\n```sh\n(14)$ git cherry-pick 5ea5173\n```\n\n<a name=\"delete-stale-local-branches\"></a>\n### Я хочу удалить локальные ветки, которые были удалены в upstream\nКак только Вы слили пулл-реквест на GitHub, Вам предлагают удалить слитую ветку из Вашего форка. Если Вы не планируете продолжать работу в этой ветке, то для поддержания рабочей копии в чистоте Вы можете удалить локальные копии ненужных веток, чтобы не путаться в них.\n\n```sh\n$ git fetch -p upstream\n```\n\nгде `upstream` - удаленная ветка, из которой Вы хотите получить изменения.\n\n<a name=\"restore-a-deleted-branch\"></a>\n### Я нечаянно удалил мою ветку\n\nЕсли Вы регулярно отправляете изменения в удаленное хранилище, большую часть времени Вы в безопасности. Но в один прекрасный момент Вы всё же можете случайно удалить Ваши ветки. Скажем, мы создали ветку и создали новый файл:\n\n```sh\n(main)$ git checkout -b my-branch\n(my-branch)$ git branch\n(my-branch)$ touch foo.txt\n(my-branch)$ ls\nREADME.md foo.txt\n```\n\nДавайте добавим его и сохраним.\n\n```sh\n(my-branch)$ git add .\n(my-branch)$ git commit -m 'foo.txt added'\n(my-branch)$ foo.txt added\n 1 files changed, 1 insertions(+)\n create mode 100644 foo.txt\n(my-branch)$ git log\n\ncommit 4e3cd85a670ced7cc17a2b5d8d3d809ac88d5012\nAuthor: siemiatj <siemiatj@example.com>\nDate:   Wed Jul 30 00:34:10 2014 +0200\n\n    foo.txt added\n\ncommit 69204cdf0acbab201619d95ad8295928e7f411d5\nAuthor: Kate Hudson <katehudson@example.com>\nDate:   Tue Jul 29 13:14:46 2014 -0400\n\n    Fixes #6: Force pushing after amending commits\n```\n\nТеперь мы переключаемся обратно на main и 'нечаянно' удаляем нашу ветку.\n\n```sh\n(my-branch)$ git checkout main\nSwitched to branch 'main'\nYour branch is up-to-date with 'origin/main'.\n(main)$ git branch -D my-branch\nDeleted branch my-branch (was 4e3cd85).\n(main)$ echo О, нет, моя ветка удалена!\nО, нет, моя ветка удалена!\n```\n\nНа этом этапе Вы должны быть знакомы с 'reflog' (расширенный журнал). Он хранит историю всех действий в репозитории.\n\n```\n(main)$ git reflog\n69204cd HEAD@{0}: checkout: moving from my-branch to main\n4e3cd85 HEAD@{1}: commit: foo.txt added\n69204cd HEAD@{2}: checkout: moving from main to my-branch\n```\n\nКак мы можем видеть, у нас есть хэш коммита из удаленной ветки. Посмотрим, можем ли мы восстановить удаленную ветку.\n\n```sh\n(main)$ git checkout -b my-branch-help\nSwitched to a new branch 'my-branch-help'\n(my-branch-help)$ git reset --hard 4e3cd85\nHEAD is now at 4e3cd85 foo.txt added\n(my-branch-help)$ ls\nREADME.md foo.txt\n```\n\nВуаля! Мы вернули наш удаленный файл обратно. `git reflog` также бывает полезен, когда перебазирование срабатывает не так, как Вы хотели.\n\n### Я хочу удалить ветку\n\nЧтобы удалить ветку на удаленном репозитории:\n\n```sh\n(main)$ git push origin --delete my-branch\n```\n\nВы также можете сделать:\n\n```sh\n(main)$ git push origin :my-branch\n```\n\nЧтобы удалить локальную ветку:\n\n```sh\n(main)$ git branch -d my-branch\n```\n\nЧтобы удалить локальную ветку, которая *не была* слита с отслеживаемой веткой (заданной с помощью `--track` или `--set-upstream`) или с HEAD:\n\n```sh\n(main)$ git branch -D my-branch\n```\n\n### Я хочу удалить несколько веток\n\nСкажем, Вы хотите удалить все ветки, начинающиеся с `fix/`:\n\n```sh\n(main)$ git branch | grep 'fix/' | xargs git branch -d\n```\n\n### Я хочу переименовать ветку\n\nЧтобы переименовать текущую (локальную) ветку:\n\n```sh\n(main)$ git branch -m new-name\n```\n\nЧтобы переименовать другую (локальную) ветку:\n\n```sh\n(main)$ git branch -m old-name new-name\n```\n\n<a name=\"working-on-checkout-remote-branch\"></a>\n### Я хочу перейти на удаленную ветку, над которой работает кто-то еще\n\nВо-первых, получим все ветки из удаленного репозитория:\n\n```sh\n(main)$ git fetch --all\n```\n\nСкажем, Вы хотите перейти на `daves` из удаленного репозитория.\n\n```sh\n(main)$ git checkout --track origin/daves\nBranch daves set up to track remote branch daves from origin.\nSwitched to a new branch 'daves'\n```\n\n(`--track` - это сокращение для `git checkout -b [branch] [remotename]/[branch]`)\n\nЭто создаст Вам локальную копию ветки `daves` и после `push` обновления также появятся в удаленном репозитории.\n\n### Я хочу создать новую удаленную ветку из текущей локальной\n\n```sh\n$ git push <remote> HEAD\n```\n\nЕсли Вы хотите, чтобы текущая локальная ветка отслеживала соответствующую удаленную (upstream) ветку, тогда выполните следующее:\n\n```sh\n$ git push -u <remote> HEAD\n```\n\nВ режиме `upstream` или в режиме `simple` (по-умолчанию в Git 2.0) параметра `push.default`, следующая команда отправит текущую ветку в удаленную ветку, которая была ранее зарегистрирована с помощью -u :\n\n```sh\n$ git push\n```\n\nПоведение других режимов `git push` описано в документации на push.default.\n\n### Я хочу настроить локальную ветку на отслеживание удаленной (upstream) ветки\n\nВы можете настроить текущую локальную ветку на отслеживание удаленной (upstream) ветки используя:\n\n```sh\n$ git branch --set-upstream-to [remotename]/[branch]\n# или для краткости:\n$ git branch -u [remotename]/[branch]\n```\n\nДля настройки отслеживаемой удаленной ветки на другую локальную ветку:\n\n```sh\n$ git branch -u [remotename]/[branch] [local-branch]\n```\n\n<a name=\"head-to-track-remote-branch\"></a>\n### Я хочу настроить HEAD на отслеживание основной удаленной ветки\n\nПри просмотре удаленных веток можно увидеть какую удаленную ветку отслеживает HEAD. Может оказаться, что это не та ветка что нужно.\n\n```sh\n$ git branch -r\n  origin/HEAD -> origin/gh-pages\n  origin/main\n```\n\nЧтобы `origin/HEAD` отслеживала `origin/main`, выполните команду:\n\n```sh\n$ git remote set-head origin --auto\norigin/HEAD set to main\n```\n\n### Я сделал изменения в неправильной ветке\n\nВы сделали несохраненные изменения, а потом поняли, что находитесь не в той ветке. Отложите эти изменения, а затем примените их к нужной ветке:\n\n```sh\n(wrong_branch)$ git stash\n(wrong_branch)$ git checkout <correct_branch>\n(correct_branch)$ git stash apply\n```\n\n## Перебазирование (rebase) и слияние (merge)\n\n<a name=\"undo-rebase\"></a>\n### Я хочу отменить перебазирование/слияние\n\nВы можете слить/перебазировать Вашу ветку с неправильной веткой. А также бывают случаи, когда Вы не можете предугадать успешно ли завершится процесс перебазирования/слияния. Git сохраняет исходный указатель HEAD в переменную ORIG_HEAD перед тем как приступить к опасным операциям, так что вернуть ветку на состояние до перебазирования/слияния просто.\n\n```sh\n(my-branch)$ git reset --hard ORIG_HEAD\n```\n\n<a name=\"force-push-rebase\"></a>\n### Я сделал перебазирование, но я не хочу делать принудительный push\n\nК сожалению, вы должны сделать принудительный push, если хотите, чтобы изменения были отражены на удаленной ветке. Это потому что у вас  изменена история. Удаленная ветка не примет изменения, если не сделать принудительный push. Это одна из основных причин, по которым большинство людей основывает свой рабочий процесс на слиянии вместо перебазирования - большие команды могут столкнуться с проблемами, если разработчики будут делать принудительный `push`. Используйте это с осторожностью. Безопасный способ использовать перебазирование - это не отражать Ваши изменения напрямую на удаленную ветку, а вместо этого делать следующее:\n\n```sh\n(main)$ git checkout my-branch\n(my-branch)$ git rebase -i main\n(my-branch)$ git checkout main\n(main)$ git merge --ff-only my-branch\n```\n\nЧтобы узнать больше, см. [эту SO ветку](https://stackoverflow.com/questions/11058312/how-can-i-use-git-rebase-without-requiring-a-forced-push).\n\n<a name=\"interactive-rebase\"></a>\n### Я хочу объединить коммиты\n\nПредположим, что Вы работаете в ветке, которая стала или станет пулл-реквестом в `main`. В простейшем случае когда всё, что Вы хотите сделать - это объединить *все* коммиты в один единственный коммит и Вам не важны временные метки, Вы можете сделать сброс и заново сделать коммит. Убедитесь, что ветка main обновлена и Ваши изменения сохранены, затем:\n\n```sh\n(my-branch)$ git reset --soft main\n(my-branch)$ git commit -am \"New awesome feature\"\n```\n\nЕсли Вы хотите больше контроля, а также сохранить метки времени, Вам нужно сделать кое-что, называемое интерактивным перебазированием:\n\n```sh\n(my-branch)$ git rebase -i main\n```\n\nЕсли Вы не работаете с другой веткой, можете делать перебазирование относительно Вашей `HEAD`. Например, если Вы хотите объединить последние два коммита, Вам нужно делать перебазирование относительно `HEAD~2`. Для последних 3 - `HEAD~3` и т.д.\n\n```sh\n(main)$ git rebase -i HEAD~2\n```\n\nПосле того, как запустите интерактивное перебазирование, Вы увидите нечто подобное в Вашем текстовом редакторе:\n\n```vim\npick a9c8a1d Some refactoring\npick 01b2fd8 New awesome feature\npick b729ad5 fixup\npick e3851e8 another fix\n\n# Rebase 8074d12..b729ad5 onto 8074d12\n#\n# Commands:\n#  p, pick = use commit\n#  r, reword = use commit, but edit the commit message\n#  e, edit = use commit, but stop for amending\n#  s, squash = use commit, but meld into previous commit\n#  f, fixup = like \"squash\", but discard this commit's log message\n#  x, exec = run command (the rest of the line) using shell\n#\n# These lines can be re-ordered; they are executed from top to bottom.\n#\n# If you remove a line here THAT COMMIT WILL BE LOST.\n#\n# However, if you remove everything, the rebase will be aborted.\n#\n# Note that empty commits are commented out\n```\n\nВсе строки, начинающиеся с `#` являются комментариями и не оказывают влияния на перебазирование.\n\nТеперь замените команды `pick` на команды, перечисленные ниже. Также Вы можете удалить коммиты, удалив соответствующие строки.\n\nНапример, если Вы хотите **оставить только старейший коммит и объединить все последующие коммиты во второй коммит**, Вам нужно рядом с каждым коммитом кроме первого и второго вместо `pick` написать `f`:\n\n```vim\npick a9c8a1d Some refactoring\npick 01b2fd8 New awesome feature\nf b729ad5 fixup\nf e3851e8 another fix\n```\n\nЕсли Вы хотите объединить эти коммиты **и переименовать коммит**, Вам нужно дополнительно добавить `r` рядом со вторым коммитом или просто используйте `s` вместо `f`:\n\n```vim\npick a9c8a1d Some refactoring\npick 01b2fd8 New awesome feature\ns b729ad5 fixup\ns e3851e8 another fix\n```\n\nТеперь Вы можете переименовать коммит в следующем запросе, который появится.\n\n```vim\nNewer, awesomer features\n\n# Please enter the commit message for your changes. Lines starting\n# with '#' will be ignored, and an empty message aborts the commit.\n# rebase in progress; onto 8074d12\n# You are currently editing a commit while rebasing branch 'main' on '8074d12'.\n#\n# Changes to be committed:\n#   modified:   README.md\n#\n\n```\n\nЕсли всё успешно, Вы увидите что-то вроде:\n\n```sh\n(main)$ Successfully rebased and updated refs/heads/main.\n```\n\n#### Безопасная стратегия слияния\n`--no-commit` производит слияние, но не делает коммит результата, давая пользователю возможность проверить и доработать результат слияния перед коммитом. `no-ff` сохраняет доказательства того, что когда-то существовала ветка feature, сохраняя цельность истории проекта.\n\n```sh\n(main)$ git merge --no-ff --no-commit my-branch\n```\n\n#### Мне нужно слить ветку в единственный коммит\n\n```sh\n(main)$ git merge --squash my-branch\n```\n\n<a name=\"rebase-unpushed-commits\"></a>\n#### Я хочу объединить только неопубликованные коммиты\n\nИногда у Вас бывает несколько временных коммитов, которые Вы хотите объединить перед публикацией в upstream. Вы не хотите ненароком объединить свои коммиты с уже опубликованными, потому что кто-то уже мог работать с ними.\n\n```sh\n(main)$ git rebase -i @{u}\n```\n\nЭто выполнит интерактивное перебазирование со списком еще не опубликованных коммитов и Вы сможете безопасно упорядочить/исправить/объединить коммиты из списка.\n\n#### Мне нужно прервать слияние\n\nИногда слияние может создавать проблемы в некоторых файлах. В таких случаях мы можем воспользоваться опцией `abort` для прерывания текущего процесса разрешения конфликтов и попробовать вернуться к состоянию перед слиянием.\n\n```sh\n(my-branch)$ git merge --abort\n```\n\nЭта команда доступна начиная с версии Git >= 1.7.4\n\n### Мне нужно обновить родительский коммит моей ветки\n\nСкажем, у меня есть ветка main, ветка feature-1, выросшая из main, и ветка feature-2, выросшая из feature-1. Если я сделаю коммит в feature-1, тогда родительский коммит ветки feature-2 будет не тем, что нужно (это должна быть верхушка feature-1, поскольку мы ответвились от неё). Мы можем исправить это с помощью `git rebase --onto`.\n\n```sh\n(feature-2)$ git rebase --onto feature-1 <первый коммит из feature-2, который Вы не хотите переносить> feature-2\n```\n\nЭто помогает в тех случаях, когда у Вас одна функция основывается на другой функции, которая еще не слита, и все исправления feature-1 должны быть отражены в feature-2.\n\n### Проверить, что все коммиты ветви были слиты\n\nДля проверки того, что все коммиты ветки слиты в другую ветку, Вам нужно сравнить вершины (или любые коммиты) этих ветвей:\n\n```sh\n(main)$ git log --graph --left-right --cherry-pick --oneline HEAD...feature/120-on-scroll\n```\n\nЭто расскажет Вам обо всех коммитах, которые есть в одной, но отсутствуют в другой ветке и выдаст список всех различий ветвей. Или можете сделать так:\n\n```sh\n(main)$ git log main ^feature/120-on-scroll --no-merges\n```\n\n### Возможные проблемы интерактивного перебазирования\n\n<a name=\"noop\"></a>\n#### Экран перебазирования говорит 'noop'\n\nЕсли Вы видите это:\n```\nnoop\n```\n\nЭто значит, что Вы пытаетесь сделать перебазирование в ветку, которая уже имеет идентичный коммит или она *впереди* текущей ветки. Вы может попробовать:\n\n- удостовериться что Ваша ветка main находится там, где она должна быть\n- вместо этого перебазировать `HEAD~2` или что-то более раннее\n\n<a name=\"merge-conflict\"></a>\n#### Здесь были конфликты\n\nЕсли Вам не удается успешно завершить перебазирование, то, возможно, Вам придется разрешать конфликты.\n\nДля начала запустите `git status`, чтобы увидеть какие файлы содержат конфликты:\n\n```sh\n(my-branch)$ git status\nOn branch my-branch\nChanges not staged for commit:\n  (use \"git add <file>...\" to update what will be committed)\n  (use \"git checkout -- <file>...\" to discard changes in working directory)\n\n  both modified:   README.md\n```\n\nВ данном примере `README.md` содержит конфликты. Откройте файл и взгляните на следующее:\n\n```vim\n   <<<<<<< HEAD\n   some code\n   =========\n   some code\n   >>>>>>> new-commit\n```\n\nВам нужно выбрать между кодом, который был добавлен в Вашем новом коммите (в данном примере, это все от средней линии до `new-commit`) и Вашей `HEAD`.\n\nЕсли Вы хотите сохранить версию из какой-то одной ветки, то используйте `--ours` или `--theirs`:\n\n```sh\n(main*)$ git checkout --ours README.md\n```\n\n- Во время *слияния* используйте `--ours` для сохранения изменений из локальной ветки или `--theirs` для сохранения изменений из другой ветки.\n- Во время *перебазирования* используйте `--theirs` для сохранения изменений из локальной ветки или `--ours` для сохранения изменений из другой ветки. Для объяснения такого обмена см. [эту заметку в документации Git](https://git-scm.com/docs/git-rebase#Documentation/git-rebase.txt---merge).\n\nЕсли слияние более сложное, можете воспользоваться визуальным редактором различий:\n\n```sh\n(main*)$ git mergetool -t opendiff\n```\n\nПосле разрешения всех конфликтов и тестирования кода подготовьте файлы, которые Вы изменили `git add`, а затем продолжите перебазирование с помощью `git rebase --continue`\n\n```sh\n(my-branch)$ git add README.md\n(my-branch)$ git rebase --continue\n```\n\nЕсли после разрешения всех конфликтов, Вы получили точно такое же дерево, какое было перед коммитом, то вместо этого Вам нужно сделать `git rebase --skip`.\n\nВ любой момент Вы можете остановить перебазирование и вернуть ветку в начальное состояние, выполнив:\n\n```sh\n(my-branch)$ git rebase --abort\n```\n\n<a name=\"stashing\"></a>\n## Отложенные изменения (stash)\n\n### Отложить все правки\n\nЧтобы отложить все правки в рабочем каталоге\n\n```sh\n$ git stash\n```\n\nЕсли Вы хотите отложить заодно и неотслеживаемые файлы, добавьте опцию `-u`.\n\n```sh\n$ git stash -u\n```\n\n### Отложить заданные файлы\n\nОтложить только один файл из рабочей папки\n\n```sh\n$ git stash push working-directory-path/filename.ext\n```\n\nОтложить несколько файлов из рабочей папки\n\n```sh\n$ git stash push working-directory-path/filename1.ext working-directory-path/filename2.ext\n```\n\n<a name=\"stash-msg\"></a>\n### Отложить с сообщением\n\n```sh\n$ git stash save <message>\n```\n\n<a name=\"stash-apply-specific\"></a>\n### Применить заданный stash из списка\n\nВо-первых, проверьте список отложенных изменений, используя\n\n```sh\n$ git stash list\n```\n\nЗатем примените заданный stash из списка, используя\n\n```sh\n$ git stash apply \"stash@{n}\"\n```\n\nЗдесь 'n' показывает позицию stash-а в стеке. Верхний stash имеет позицию 0.\n\n## Поиск\n\n### Я хочу найти строку в коммитах\n\nЧтобы найти коммиты с заданной строкой, используйте следующее:\n\n```sh\n$ git log -S \"string to find\"\n```\n\nОбщие параметры:\n\n- `--source` показывает ссылки, от которых можно добраться до каждого коммита.\n\n- `--all` ищет во всех ветках.\n\n- `--reverse` выводит коммиты в обратном порядке, это значит, что вверху будет первый коммит, в котором сделано это изменение.\n\n<a name=\"find-by-committer\"></a>\n### Я хочу искать по автору или сохранившему изменения (committer)\n\nНайти все коммиты по автору или сохранившему изменения:\n\n```sh\n$ git log --author=<name or email>\n$ git log --committer=<name or email>\n```\n\nНе забывайте, что автор и сохранивший изменения - это не всегда один и тот же человек. `--author` - это тот, кто написал код, а `--committer` - тот, кто сохранил код, написанный автором.\n\n### Я хочу получить список коммитов, содержащих заданный файл\n\nЧтобы найти все коммиты, содержащие заданный файл, Вы можете использовать:\n\n```sh\n$ git log -- <path to file>\n```\n\nОбычно Вы задаете точный путь, но можете использовать подстановочные знаки:\n\n```sh\n$ git log -- **/*.js\n```\n\nПри использовании подстановочных знаков используйте `--name-status` для просмотра списка файлов, сохраненных в каждом коммите:\n\n```sh\n$ git log --name-status -- **/*.js\n```\n\n<a name=\"view-commit-history-for-specific-function\"></a>\n### Я хочу посмотреть историю коммитов для отдельной функции\n\nДля отслеживания эволюции отдельной функции Вы можете использовать:\n\n```sh\n$ git log -L :FunctionName:FilePath\n```\n\nЗаметьте, что Вы можете добавить и другие опции команды `git log`, вроде [диапазона ревизий](https://git-scm.com/docs/gitrevisions) и [выборки коммитов](https://git-scm.com/docs/git-log/#_commit_limiting).\n\n### Найти метки для заданного коммита\n\nЧтобы найти все метки для заданного коммита:\n\n```sh\n$ git tag --contains <commitid>\n```\n\n## Субмодули\n\n<a name=\"clone-submodules\"></a>\n### Клонировать все субмодули\n\n```sh\n$ git clone --recursive git://github.com/foo/bar.git\n```\n\nЕсли уже клонированы:\n\n```sh\n$ git submodule update --init --recursive\n```\n\n<a name=\"delete-submodule\"></a>\n### Удалить субмодуль\n\nСоздание субмодуля довольно прямолинейно, чего не скажешь об удалении. Команды, которые Вам нужны:\n\n```sh\n$ git submodule deinit submodulename\n$ git rm submodulename\n$ git rm --cached submodulename\n$ rm -rf .git/modules/submodulename\n```\n\n## Разное\n\n### Восстановить удаленный файл\n\nСначала нужно найти последний коммит, где файл еще существует:\n\n```sh\n$ git rev-list -n 1 HEAD -- filename\n```\n\nЗатем взять версию файла из коммита непосредственно перед удалением:\n\n```\ngit checkout deletingcommitid^ -- filename\n```\n\n### Удалить метку\n\n```sh\n$ git tag -d <tag_name>\n$ git push <remote> :refs/tags/<tag_name>\n```\n\n<a name=\"recover-tag\"></a>\n### Восстановить удаленную метку\n\nЕсли хотите восстановить метку, которая была удалена, Вы можете сделать следующее: во-первых, Вам нужно найти недостижимую метку:\n\n```sh\n$ git fsck --unreachable | grep tag\n```\n\nЗапомните для себя хэш метки. Затем восстановите удаленную метку, используя команду [`git update-ref`](https://git-scm.com/docs/git-update-ref):\n\n```sh\n$ git update-ref refs/tags/<tag_name> <hash>\n```\n\nВаша метка была восстановлена.\n\n### Удаленный патч\n\nЕсли кто-то прислал Вам пулл-реквест на GitHub, но потом удалил свой форк, то вы не сможете клонировать его репозиторий или использовать `git am`, поскольку [.diff, .patch](https://github.com/blog/967-github-secrets) URL'ы становятся недоступными. Но Вы можете сделать `checkout` самого пулл-реквеста используя [специальные GitHub's refs](https://gist.github.com/piscisaureus/3342247). Для получения содержимого PR#1 в новую ветку с названием pr_1:\n\n```sh\n$ git fetch origin refs/pull/1/head:pr_1\nFrom github.com:foo/bar\n * [new ref]         refs/pull/1/head -> pr_1\n```\n\n### Экспорт репозитория в Zip-файл\n\n```sh\n$ git archive --format zip --output /full/path/to/zipfile.zip main\n```\n### Как опубликовать ветку и метку, если они имеют одинаковые имена\n\nЕсли в удаленном репозитории есть метка с таким же именем, как и ветка <branch>, то после выполнения команды `$ git push <remote> <branch>` Вы получите следующую ошибку:\n\n```sh\n$ git push origin <branch>\nerror: dst refspec same matches more than one.\nerror: failed to push some refs to '<git server>'\n```\n\nИсправить это можно, указав Вы хотите опубликовать именно ветку.\n\n```sh\n$ git push origin refs/heads/<branch-name>\n```\n\nЕсли Вы хотите опубликовать метку с таким же названием, как у ветки, используйте сходную команду.\n\n```sh\n$ git push origin refs/tags/<tag-name>\n```\n\n## Отслеживание файлов\n\n<a name=\"change-file-name-capitalization-without-changing-contents\"></a>\n### Я хочу изменить регистр в имени файла, не меняя содержимое файла\n\n```sh\n(main)$ git mv --force myfile MyFile\n```\n\n### Я хочу переписать локальные файлы при выполнении git pull\n\n```sh\n(main)$ git fetch --all\n(main)$ git reset --hard origin/main\n```\n\n<a name=\"remove-from-git\"></a>\n### Я хочу удалить файл из git, но оставить сам файл\n\n```sh\n(main)$ git rm --cached log.txt\n```\n\n### Я хочу откатить файл до заданной ревизии\n\nПолагая, что хэш желаемого коммита c5f567:\n\n```sh\n(main)$ git checkout c5f567 -- file1/to/restore file2/to/restore\n```\n\nЕсли вы хотите откатить файл к состоянию на 1 коммит раньше, чем c5f567, задайте хэш коммита как c5f567~1:\n\n```sh\n(main)$ git checkout c5f567~1 -- file1/to/restore file2/to/restore\n```\n\n### Я хочу получить список изменений в заданном файле из разных коммитов или веток\n\nПолагая, что Вы хотите сравнить последний коммит с файлом из коммита c5f567:\n\n```sh\n$ git diff HEAD:path_to_file/file c5f567:path_to_file/file\n# или\n$ git diff HEAD c5f567 -- path_to_file/file\n```\n\nАналогично для веток:\n\n```sh\n$ git diff main:path_to_file/file staging:path_to_file/file\n# или\n$ git diff main staging -- path_to_file/file\n```\n\n### Я хочу, чтобы Git игнорировал изменения в определенном файле\n\nЭто бывает нужно для шаблонов конфигураций или других файлов, предназначенных для добавления учетных записей, которые не нужно коммитить.\n\n```sh\n$ git update-index --assume-unchanged file-to-ignore\n```\n\nОбратите внимание, что это *не* удаляет файл из контроля версий - он всего лишь игнорируется локально. Чтобы отменить это и сказать Git снова отслеживать изменения, выполните обратную команду:\n\n```sh\n$ git update-index --no-assume-unchanged file-to-stop-ignoring\n```\n\n## Отладка с помощью Git\n\nКоманда [git-bisect](https://git-scm.com/docs/git-bisect) с помощью двоичного поиска находит в истории Git коммит, в котором впервые появилась ошибка.\n\nПусть вы находитесь на ветке `main` и хотите найти коммит, которых поломал некую функцию. Вы начинаете процедуру поиска:\n\n```sh\n$ git bisect start\n```\n\nЗатем вы должны указать коммит, где функция поломана (bad), коммит, где функция работает правильно (good). Предположим, что *текущая* версия поломана, а `v1.1.1` - работоспособная:\n\n```sh\n$ git bisect bad\n$ git bisect good v1.1.1\n```\n\nПосле этого `git-bisect` выберет коммит из середины заданного вами диапазона, перейдет на него и спросит у вас: хороший он или плохой. Вы увидите что-то вроде:\n\n```sh\n$ Bisecting: 5 revision left to test after this (roughly 5 step)\n$ [c44abbbee29cb93d8499283101fe7c8d9d97f0fe] Commit message\n$ (c44abbb)$\n```\n\nВы проверите хороший ли коммит. Если хороший:\n\n```sh\n$ (c44abbb)$ git bisect good\n```\n\nи `git-bisect` выберет другой коммит. Этот процесс (выбора `good` или `bad`) будет повторяться до тех пор, пока диапазон поиска не сузится до единственного коммита, после чего команда выведет описание **первого** плохого коммита.\n\n## Конфигурация\n\n### Я хочу добавить псевдонимы для некоторых команд Git\n\nВ OS X и Linux Ваш файл конфигурации Git хранится в `~/.gitconfig`.  В качестве примера я добавил некоторые псевдонимы, которые сам использую для краткости (а также некоторые из моих типичных опечаток), в раздел `[alias]` как показано ниже:\n\n```vim\n[alias]\n    a = add\n    amend = commit --amend\n    c = commit\n    ca = commit --amend\n    ci = commit -a\n    co = checkout\n    d = diff\n    dc = diff --changed\n    ds = diff --staged\n    extend = commit --amend -C HEAD\n    f = fetch\n    loll = log --graph --decorate --pretty=oneline --abbrev-commit\n    m = merge\n    one = log --pretty=oneline\n    outstanding = rebase -i @{u}\n    reword = commit --amend --only\n    s = status\n    unpushed = log @{u}\n    wc = whatchanged\n    wip = rebase -i @{u}\n    zap = fetch -p\n    day = log --reverse --no-merges --branches=* --date=local --since=midnight --author=\\\"$(git config --get user.name)\\\"\n    delete-merged-branches = \"!f() { git checkout --quiet main && git branch --merged | grep --invert-match '\\\\*' | xargs -n 1 git branch --delete; git checkout --quiet @{-1}; }; f\"\n```\n\n### Я хочу добавить в свой репозиторий пустую папку\n\nВы не можете этого сделать! Git просто не поддерживает этого, но есть уловка. Вы можете создать файл .gitignore в папке со следующим содержанием:\n\n```\n # Игнорировать всё в этой папке\n *\n # Кроме этого файла\n !.gitignore\n```\n\nДругой общеиспользуемый способ - это создать в папке пустой файл с названием .gitkeep.\n\n```sh\n$ mkdir mydir\n$ touch mydir/.gitkeep\n```\n\nВы можете назвать его просто .keep , в этом случае вторая строка выше будет `touch mydir/.keep`\n\n### Я хочу сохранить имя пользователя и пароль для репозитория\n\nУ Вас может быть репозиторий, требующий авторизации. В этом случае вы можете сохранить на время имя пользователя и пароль, и Вам не потребуется вводить их при каждом вызове push или pull. Помощник по учетным записям сделает это за Вас.\n\n```sh\n$ git config --global credential.helper cache\n# Включает кэширование памяти учетных записей\n```\n\n```sh\n$ git config --global credential.helper 'cache --timeout=3600'\n# Задает таймаут для кэша 1 час (задается в секундах)\n```\nНайти помощника по учетным записям:\n\n```sh\n$ git help -a | grep credential\n# Покажет доступных помощников по учетным записям\n```\n\nСпецифическое кэширование учетных записей для некоторых ОС:\n\n```sh\n$ git config --global credential.helper osxkeychain\n# Для OSX\n```\n\n```sh\n$ git config --global credential.helper manager\n# Git for Windows 2.7.3+\n```\n\n```sh\n$ git config --global credential.helper gnome-keyring\n# Ubuntu и другие дистрибутивы, основанные на GNOME\n```\n\nВероятно можно найти и других помощников по учетным записям для других дистрибутивов и ОС.\n\n### Я хочу, чтобы Git игнорировал изменения разрешений и прав файлов\n\n```sh\n$ git config core.fileMode false\n```\n\nЕсли Вы хотите задать это поведение по-умолчанию для всех авторизованных пользователей, тогда используйте:\n\n```sh\n$ git config --global core.fileMode false\n```\n\n### Я хочу задать данные пользователя в глобальных настройках\n\nЧтобы настроить информацию о пользователе, используемую во всех локальных репозиториях, в частности имя, отображаемое в истории изменений:\n\n```sh\n$ git config --global user.name “[firstname lastname]”\n```\n\nЧтобы настроить адрес электронной почты, который будет связан с каждой записью в историю:\n\n```sh\ngit config --global user.email “[valid-email]”\n```\n\n## Я не представляю что я сделал неправильно\n\nИтак, Вы в затруднении - Вы сбросили что-то или Вы слили неправильную ветку, или Вы отправили изменения с принудительной перезаписью и теперь Вы не можете найти свои коммиты. Вы знаете, что в какой-то момент было всё в порядке и Вы хотите вернуться к этому состоянию.\n\nКак раз для этого и нужен `git reflog`. `reflog` отслеживает все изменения вершины ветки, даже если на эту вершину не указывает ни единая ветвь или метка. В принципе, всякий раз при изменении HEAD, в reflog добавляется новая запись. К сожалению, это работает только с локальными репозиториями и отслеживаются только движения (а не, например, изменения файла, которые не были никуда записаны).\n\n```sh\n(main)$ git reflog\n0a2e358 HEAD@{0}: reset: moving to HEAD~2\n0254ea7 HEAD@{1}: checkout: moving from 2.2 to main\nc10f740 HEAD@{2}: checkout: moving from main to 2.2\n```\n\nreflog выше показывает переход с ветки main на ветку 2.2 и обратно. Затем происходит жесткий сброс на старый коммит. Самое последнее действие находится вверху с надписью `HEAD@{0}`.\n\nЕсли Вы случайно переместитесь назад, то reflog будет содержать коммит (0254ea7), на который указывала ветка main до того, как Вы случайно выбросили 2 коммита.\n\n```sh\n$ git reset --hard 0254ea7\n```\n\nС помощью `git reset` можно вернуть ветку main обратно на коммит, на котором она была прежде. Это обеспечивает безопасность при случайном изменении истории.\n\n(взято из [Источник](https://www.atlassian.com/git/tutorials/rewriting-history/git-reflog)).\n\n<a name=\"git-shortcuts\"></a>\n## Сокращения для команд Git\n\n### Git Bash\n\nКак только Вы освоитесь с командами, описанными выше, возможно, Вам захочется написать сокращения для Git Bash. Это позволит Вас работать гораздо быстрее, выполняя сложные задачи с помощью весьма коротких команд.\n\n```sh\nalias sq=squash\n\nfunction squash() {\n    git rebase -i HEAD~$1\n}\n```\n\nСкопируйте эти команды в Ваш .bashrc или .bash_profile.\n\n### PowerShell в Windows\n\nЕсли Вы пользуетесь PowerShell на Windows, то и здесь Вы можете настроить псевдонимы и функции. Добавьте эти команды в Ваш профиль, путь к которому указан в переменной `$profile`. Узнать больше о профилях можно на портале документации Microsoft [About Profiles](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_profiles).\n\n```powershell\nSet-Alias sq Squash-Commits\n\nfunction Squash-Commits {\n  git rebase -i HEAD~$1\n}\n```\n\n# Другие ресурсы\n\n## Книги\n\n* [Learn Enough Git to Be Dangerous](https://www.learnenough.com/git-tutorial) - Книга Майкла Хартла, посвященная Git с самых основ\n* [Pro Git](https://git-scm.com/book/ru/v2) - великолепная книга Скотта Чакона и Бена Страуба про Git\n* [Git Internals](https://github.com/pluralsight/git-internals-pdf) - еще одна великолепная книга Скотта Чакона, посвященная Git\n* [Nasa handbook](https://www.nasa.gov/sites/default/files/atoms/files/nasa_systems_engineering_handbook.pdf)\n\n## Учебники\n\n* [19 Git Tips For Everyday Use](https://www.alexkras.com/19-git-tips-for-everyday-use) - Список полезных однострочников Git\n* [Atlassian's Git tutorial](https://www.atlassian.com/git/tutorials) Получите Git сразу с учебниками от начального до продвинутого уровня.\n* [Изучаем ветвление в Git](https://learngitbranching.js.org/) Интерактивный веб-учебник по ветвлению/слиянию/перебазированию\n* [Конструктивно о слиянии и перебазировании в Git](https://medium.com/@porteneuve/getting-solid-at-git-rebase-vs-merge-4fa1a48c53aa)\n* [Git Commands and Best Practices Cheat Sheet](https://zeroturnaround.com/rebellabs/git-commands-and-best-practices-cheat-sheet) - Шпаргалка Git с подробными пояснениями\n* [Git изнутри](https://codewords.recurse.com/issues/two/git-from-the-inside-out) - Учебник, погружающий во внутренности Git\n* [git-workflow](https://github.com/asmeurer/git-workflow) - Руководство от [Aaron Meurer](https://github.com/asmeurer) по использованию Git в совместной разработке проектов с открытым исходным кодом\n* [GitHub как рабочий процесс](https://hugogiraudel.com/2015/08/13/github-as-a-workflow/) - Интересный подход к использованию GitHub в качестве рабочего процесса, в частности с пустыми пулл-реквестами\n* [Githug](https://github.com/Gazler/githug) - Игра для изучения более общих рабочих процессов Git\n* [learnGitBranching](https://github.com/pcottle/learnGitBranching) - Изучение ветвлений git в игровой форме.\n\n## Скрипты и инструменты\n\n* [firstaidgit.io](http://firstaidgit.io/) Выборка наиболее частых вопросов и ответов по Git c поиском\n* [git-extra-commands](https://github.com/unixorn/git-extra-commands) - сборник полезных дополнительных скриптов для Git\n* [git-extras](https://github.com/tj/git-extras) - GIT utilities -- статистика репозитория, REPL, генерация журнала изменений, статистика по авторам изменений и многое другое\n* [git-fire](https://github.com/qw3rtman/git-fire) - git-fire  - это плагин для Git, который предупреждает при потенциально опасных действиях, таких как: добавление всех файлов из текущей папки, создание коммита и публикация измений в новую ветку (для предотвращения конфликтов при слиянии).\n* [git-tips](https://github.com/git-tips/tips) - Краткие советы по Git\n* [git-town](https://github.com/Originate/git-town) - Общая высокоуровневая поддержка рабочего процесса Git! http://www.git-town.com\n\n## Графические клиенты\n* [GitKraken](https://www.gitkraken.com/) - роскошный Git-клиент для Windows, Mac и Linux\n* [git-cola](https://git-cola.github.io/) - еще один Git-клиент для Windows и OS X\n* [GitUp](https://github.com/git-up/GitUp) - новый графический клиент, имеющий весьма своеобразные методы работы со сложностями Git\n* [gitx-dev](https://rowanj.github.io/gitx/) - еще один графический Git-клиент для OS X\n* [Sourcetree](https://www.sourcetreeapp.com/) - Простота и мощь в красивом и свободном графическом Git-клиенте. Для Windows и Mac.\n* [Tower](https://www.git-tower.com/) - графический Git-клиент для OS X (платный)\n* [tig](https://jonas.github.io/tig/) - консольный текстовый интерфейс для Git\n* [Magit](https://magit.vc/) - интерфейс для Git, реализованный в виде модуля Emacs.\n* [GitExtensions](https://github.com/gitextensions/gitextensions) - расширение оболочки, плагин для Visual Studio 2010-2015 и автономный инструмент для управления репозиториями Git.\n* [Fork](https://git-fork.com/) - быстрый и дружелюбный Git-клиент для Mac (бета)\n* [gmaster](https://gmaster.io/) - Git-клиент для Windows с трехсторонним слиянием, обнаружением рефакторинга, семантическим сравнением и слиянием (бета)\n* [gitk](https://git-scm.com/docs/gitk) - Git-клиент под Linux для просмотра состояния репозитория.\n* [SublimeMerge](https://www.sublimemerge.com/) - Шустрый, расширяемый клиент для трехстороннего слияния, мощного поиска и подсветки синтаксиса. В активной разработке.\n"
  },
  {
    "path": "README_vi.md",
    "content": "# Flight rules cho Git\n\n🌍\n*[English](README.md) ∙ [Español](README_es.md)  ∙  [Русский](README_ru.md) ∙ [繁體中文](README_zh-TW.md) ∙ [简体中文](README_zh-CN.md) ∙ [한국어](README_kr.md)  ∙  [Tiếng Việt](README_vi.md) ∙ [Français](README_fr.md) ∙ [日本語](README_ja.md)*\n\n#### \"Flight rules\" là gì?\n\nLà tài liệu hướng dẫn cho các phi hành gia vũ trụ (và tại đây, cho các lập trình viên sử dụng Git) về những việc cần làm khi có sai lầm xảy ra.\n\n>  *Flight Rules* là những kiến thức vất vả kiếm được trong các hướng dẫn sử dụng chỉ ra, từng bước, phải làm gì nếu X xảy ra và tại sao. Về cơ bản, chúng là các chuẩn quy trình thực hiện rất chi tiết cho từng kịch bản cụ thể . [...]\n\n> NASA qua thời gian đã ghi lại những sai lầm, thảm hoạ và giải pháp của chúng tôi kể từ đầu những năm 1960, khi các đội mặt đất trong thời kỳ chương trình Mercury bắt đầu thu thập \"các bài học kinh nghiệm\" thành một bản yếu lược liệt kê hàng nghìn tình huống có vấn đề, từ lỗi động cơ đến các tay cầm bị bẻ cong đến trục trặc máy tính, và các giải pháp của họ.\n\n&mdash; Chris Hadfield, *Sổ Tay Phi Hành Gia*.\n\n#### Quy chuẩn cho tài liệu này\n\nĐể  chuyền tải rõ ràng, tất cả các ví dụ trong tài liệu này sử dụng bash prompt được tuỳ chỉnh để chỉ ra nhánh hiện tại và có hay không thay đổi trong vùng chuyển tiếp (staged changes). Nhánh được đặt trong dấu ngoặc đơn và một ký tự `*` bên cạnh tên nhánh cho biết các thay đổi trong vùng chuyển tiếp.\n\nTất cả các lệnh (command) phải thi hành với phiên bản lâu đời nhất là git 2.13.0. Xem [git website](https://www.git-scm.com/) để cập nhật phiên bản git trên local của bạn.\n\n[![Join the chat at https://gitter.im/k88hudson/git-flight-rules](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/k88hudson/git-flight-rules?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Danh mục nội dung**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n  - [Repositories (Kho)](#repositories-kho)\n    - [Tôi muốn tạo một repository trên local](#t%C3%B4i-mu%E1%BB%91n-t%E1%BA%A1o-m%E1%BB%99t-repository-tr%C3%AAn-local)\n    - [Tôi muốn clone một remote repository](#t%C3%B4i-mu%E1%BB%91n-clone-m%E1%BB%99t-remote-repository)\n    - [Tôi để sai remote repository](#t%C3%B4i-%C4%91%E1%BB%83-sai-remote-repository)\n    - [Tôi muốn thêm sửa code cho repository của người khác](#t%C3%B4i-mu%E1%BB%91n-th%C3%AAm-s%E1%BB%ADa-code-cho-repository-c%E1%BB%A7a-ng%C6%B0%E1%BB%9Di-kh%C3%A1c)\n      - [Thêm sửa code với pull requests](#th%C3%AAm-s%E1%BB%ADa-code-v%E1%BB%9Bi-pull-requests)\n      - [Thêm sửa code với các patch (vá)](#th%C3%AAm-s%E1%BB%ADa-code-v%E1%BB%9Bi-c%C3%A1c-patch-v%C3%A1)\n      - [Tôi cần update fork của tôi với những thay đổi mới nhất từ repository nguyên bản](#t%C3%B4i-c%E1%BA%A7n-update-fork-c%E1%BB%A7a-t%C3%B4i-v%E1%BB%9Bi-nh%E1%BB%AFng-thay-%C4%91%E1%BB%95i-m%E1%BB%9Bi-nh%E1%BA%A5t-t%E1%BB%AB-repository-nguy%C3%AAn-b%E1%BA%A3n)\n  - [Chỉnh sửa Commit](#ch%E1%BB%89nh-s%E1%BB%ADa-commit)\n    - [Tôi vừa commit cái gì?](#t%C3%B4i-v%E1%BB%ABa-commit-c%C3%A1i-g%C3%AC)\n    - [Tôi đã viết sai vài thứ trong message (thông điệp) của commit](#t%C3%B4i-%C4%91%C3%A3-vi%E1%BA%BFt-sai-v%C3%A0i-th%E1%BB%A9-trong-message-th%C3%B4ng-%C4%91i%E1%BB%87p-c%E1%BB%A7a-commit)\n    - [Tôi đã commit với cấu hình tên và email sai](#t%C3%B4i-%C4%91%C3%A3-commit-v%E1%BB%9Bi-c%E1%BA%A5u-h%C3%ACnh-t%C3%AAn-v%C3%A0-email-sai)\n    - [Tôi muốn xoá một file từ commit trước](#t%C3%B4i-mu%E1%BB%91n-xo%C3%A1-m%E1%BB%99t-file-t%E1%BB%AB-commit-tr%C6%B0%E1%BB%9Bc)\n    - [Tôi muốn xoá hoặc loại bỏ commit mới nhất](#t%C3%B4i-mu%E1%BB%91n-xo%C3%A1-ho%E1%BA%B7c-lo%E1%BA%A1i-b%E1%BB%8F-commit-m%E1%BB%9Bi-nh%E1%BA%A5t)\n    - [Xoá/loại bỏ bất kỳ commit nào](#xo%C3%A1lo%E1%BA%A1i-b%E1%BB%8F-b%E1%BA%A5t-k%E1%BB%B3-commit-n%C3%A0o)\n    - [Tôi đã cố gắng push commit đã sửa đổi lên remote, nhưng tôi gặp thông báo lỗi](#t%C3%B4i-%C4%91%C3%A3-c%E1%BB%91-g%E1%BA%AFng-push-commit-%C4%91%C3%A3-s%E1%BB%ADa-%C4%91%E1%BB%95i-l%C3%AAn-remote-nh%C6%B0ng-t%C3%B4i-g%E1%BA%B7p-th%C3%B4ng-b%C3%A1o-l%E1%BB%97i)\n    - [Tôi đã vô tình thực hiện hard reset và tôi muốn các thay đổi của tôi.](#t%C3%B4i-%C4%91%C3%A3-v%C3%B4-t%C3%ACnh-th%E1%BB%B1c-hi%E1%BB%87n-hard-reset-v%C3%A0-t%C3%B4i-mu%E1%BB%91n-c%C3%A1c-thay-%C4%91%E1%BB%95i-c%E1%BB%A7a-t%C3%B4i)\n    - [Tôi vô tình commit và đẩy lên một merge](#t%C3%B4i-v%C3%B4-t%C3%ACnh-commit-v%C3%A0-%C4%91%E1%BA%A9y-l%C3%AAn-m%E1%BB%99t-merge)\n    - [Tôi vô tình commit và đẩy các file chứa dữ liệu nhảy cảm](#t%C3%B4i-v%C3%B4-t%C3%ACnh-commit-v%C3%A0-%C4%91%E1%BA%A9y-c%C3%A1c-file-ch%E1%BB%A9a-d%E1%BB%AF-li%E1%BB%87u-nh%E1%BA%A3y-c%E1%BA%A3m)\n    - [Tôi muốn xóa file to quá để chưa bao giờ xuất hiện trong lịch sử repository](#t%C3%B4i-mu%E1%BB%91n-x%C3%B3a-file-to-qu%C3%A1-%C4%91%E1%BB%83-ch%C6%B0a-bao-gi%E1%BB%9D-xu%E1%BA%A5t-hi%E1%BB%87n-trong-l%E1%BB%8Bch-s%E1%BB%AD-repository)\n      - [Cách khuyến khích: Sử dụng dịch vụ bên thứ ba bfg](#c%C3%A1ch-khuy%E1%BA%BFn-kh%C3%ADch-s%E1%BB%AD-d%E1%BB%A5ng-d%E1%BB%8Bch-v%E1%BB%A5-b%C3%AAn-th%E1%BB%A9-ba-bfg)\n      - [Cách có sẵn: Sử dụng git-filter-branch](#c%C3%A1ch-c%C3%B3-s%E1%BA%B5n-s%E1%BB%AD-d%E1%BB%A5ng-git-filter-branch)\n      - [Bước cuối: Đẩy lịch sử đã thay đổi của repository](#b%C6%B0%E1%BB%9Bc-cu%E1%BB%91i-%C4%91%E1%BA%A9y-l%E1%BB%8Bch-s%E1%BB%AD-%C4%91%C3%A3-thay-%C4%91%E1%BB%95i-c%E1%BB%A7a-repository)\n    - [Tôi cần thay đổi nội dung của một commit nhưng không phải là cái mới nhất](#t%C3%B4i-c%E1%BA%A7n-thay-%C4%91%E1%BB%95i-n%E1%BB%99i-dung-c%E1%BB%A7a-m%E1%BB%99t-commit-nh%C6%B0ng-kh%C3%B4ng-ph%E1%BA%A3i-l%C3%A0-c%C3%A1i-m%E1%BB%9Bi-nh%E1%BA%A5t)\n  - [Staging (sân chuyển tiếp)](#staging-s%C3%A2n-chuy%E1%BB%83n-ti%E1%BA%BFp)\n    - [Tôi muốn nâng lên stage tất cả file đang theo dõi và bỏ qua file không theo dõi](#t%C3%B4i-mu%E1%BB%91n-n%C3%A2ng-l%C3%AAn-stage-t%E1%BA%A5t-c%E1%BA%A3-file-%C4%91ang-theo-d%C3%B5i-v%C3%A0-b%E1%BB%8F-qua-file-kh%C3%B4ng-theo-d%C3%B5i)\n      - [Chỉ nâng một phần các file đang theo dõi](#ch%E1%BB%89-n%C3%A2ng-m%E1%BB%99t-ph%E1%BA%A7n-c%C3%A1c-file-%C4%91ang-theo-d%C3%B5i)\n    - [Tôi cần cho thêm các thay đổi đang trong stage vào commit trước](#t%C3%B4i-c%E1%BA%A7n-cho-th%C3%AAm-c%C3%A1c-thay-%C4%91%E1%BB%95i-%C4%91ang-trong-stage-v%C3%A0o-commit-tr%C6%B0%E1%BB%9Bc)\n    - [Tôi muốn stage một phần của một file mới, nhưng không phải toàn bộ file](#t%C3%B4i-mu%E1%BB%91n-stage-m%E1%BB%99t-ph%E1%BA%A7n-c%E1%BB%A7a-m%E1%BB%99t-file-m%E1%BB%9Bi-nh%C6%B0ng-kh%C3%B4ng-ph%E1%BA%A3i-to%C3%A0n-b%E1%BB%99-file)\n    - [Tôi muốn thêm các thay đổi trong một file vào 2 commit khác nhau](#t%C3%B4i-mu%E1%BB%91n-th%C3%AAm-c%C3%A1c-thay-%C4%91%E1%BB%95i-trong-m%E1%BB%99t-file-v%C3%A0o-2-commit-kh%C3%A1c-nhau)\n    - [Tôi cho lên stage quá nhiều thay đổi, và tôi muốn tách ra thành các commit khác nhau](#t%C3%B4i-cho-l%C3%AAn-stage-qu%C3%A1-nhi%E1%BB%81u-thay-%C4%91%E1%BB%95i-v%C3%A0-t%C3%B4i-mu%E1%BB%91n-t%C3%A1ch-ra-th%C3%A0nh-c%C3%A1c-commit-kh%C3%A1c-nhau)\n    - [Tôi muốn cho lên stage các chỉnh sửa chưa được stage và hã khỏi stage các chỉnh sửa đã stage](#t%C3%B4i-mu%E1%BB%91n-cho-l%C3%AAn-stage-c%C3%A1c-ch%E1%BB%89nh-s%E1%BB%ADa-ch%C6%B0a-%C4%91%C6%B0%E1%BB%A3c-stage-v%C3%A0-h%C3%A3-kh%E1%BB%8Fi-stage-c%C3%A1c-ch%E1%BB%89nh-s%E1%BB%ADa-%C4%91%C3%A3-stage)\n  - [Thay đổi chưa lên sân (Unstaged Edits)](#thay-%C4%91%E1%BB%95i-ch%C6%B0a-l%C3%AAn-s%C3%A2n-unstaged-edits)\n    - [Tôi muốn di chuyển các chỉnh sửa chưa lên stage sang một nhánh mới](#t%C3%B4i-mu%E1%BB%91n-di-chuy%E1%BB%83n-c%C3%A1c-ch%E1%BB%89nh-s%E1%BB%ADa-ch%C6%B0a-l%C3%AAn-stage-sang-m%E1%BB%99t-nh%C3%A1nh-m%E1%BB%9Bi)\n    - [Tôi muốn di chuyển các chỉnh sửa chưa stage của tôi đến một nhánh khác đã tồn tại](#t%C3%B4i-mu%E1%BB%91n-di-chuy%E1%BB%83n-c%C3%A1c-ch%E1%BB%89nh-s%E1%BB%ADa-ch%C6%B0a-stage-c%E1%BB%A7a-t%C3%B4i-%C4%91%E1%BA%BFn-m%E1%BB%99t-nh%C3%A1nh-kh%C3%A1c-%C4%91%C3%A3-t%E1%BB%93n-t%E1%BA%A1i)\n    - [Tôi muốn bỏ các thay đôi chưa trong commit tại local (đã lên hoặc chưa lên stage)](#t%C3%B4i-mu%E1%BB%91n-b%E1%BB%8F-c%C3%A1c-thay-%C4%91%C3%B4i-ch%C6%B0a-trong-commit-t%E1%BA%A1i-local-%C4%91%C3%A3-l%C3%AAn-ho%E1%BA%B7c-ch%C6%B0a-l%C3%AAn-stage)\n    - [Tôi muốn loại bỏ các thay đổi cụ thể chưa lên stage](#t%C3%B4i-mu%E1%BB%91n-lo%E1%BA%A1i-b%E1%BB%8F-c%C3%A1c-thay-%C4%91%E1%BB%95i-c%E1%BB%A5-th%E1%BB%83-ch%C6%B0a-l%C3%AAn-stage)\n    - [Tôi muốn loại bỏ các file cụ thể chưa lên stage](#t%C3%B4i-mu%E1%BB%91n-lo%E1%BA%A1i-b%E1%BB%8F-c%C3%A1c-file-c%E1%BB%A5-th%E1%BB%83-ch%C6%B0a-l%C3%AAn-stage)\n    - [Tôi muốn chỉ loại bỏ các thay đổi chưa lên stage tại local](#t%C3%B4i-mu%E1%BB%91n-ch%E1%BB%89-lo%E1%BA%A1i-b%E1%BB%8F-c%C3%A1c-thay-%C4%91%E1%BB%95i-ch%C6%B0a-l%C3%AAn-stage-t%E1%BA%A1i-local)\n    - [Tôi muốn loại bỏ tất cả các file chưa được theo dõi (track)](#t%C3%B4i-mu%E1%BB%91n-lo%E1%BA%A1i-b%E1%BB%8F-t%E1%BA%A5t-c%E1%BA%A3-c%C3%A1c-file-ch%C6%B0a-%C4%91%C6%B0%E1%BB%A3c-theo-d%C3%B5i-track)\n    - [Tôi muốn hạ khỏi stage một file cụ thể đã stage](#t%C3%B4i-mu%E1%BB%91n-h%E1%BA%A1-kh%E1%BB%8Fi-stage-m%E1%BB%99t-file-c%E1%BB%A5-th%E1%BB%83-%C4%91%C3%A3-stage)\n  - [Nhánh](#nh%C3%A1nh)\n    - [Tôi muốn liệt kê tất cả các nhánh](#t%C3%B4i-mu%E1%BB%91n-li%E1%BB%87t-k%C3%AA-t%E1%BA%A5t-c%E1%BA%A3-c%C3%A1c-nh%C3%A1nh)\n    - [Tạo một nhánh mới từ một commit](#t%E1%BA%A1o-m%E1%BB%99t-nh%C3%A1nh-m%E1%BB%9Bi-t%E1%BB%AB-m%E1%BB%99t-commit)\n    - [Tôi đã pull (kéo) từ/vào sai nhánh](#t%C3%B4i-%C4%91%C3%A3-pull-k%C3%A9o-t%E1%BB%ABv%C3%A0o-sai-nh%C3%A1nh)\n    - [Tôi muốn loại bỏ các commit tại local để nhánh của tôi giống như nhánh trên server](#t%C3%B4i-mu%E1%BB%91n-lo%E1%BA%A1i-b%E1%BB%8F-c%C3%A1c-commit-t%E1%BA%A1i-local-%C4%91%E1%BB%83-nh%C3%A1nh-c%E1%BB%A7a-t%C3%B4i-gi%E1%BB%91ng-nh%C6%B0-nh%C3%A1nh-tr%C3%AAn-server)\n    - [Tôi đã tạo commit lên main thay vì một nhánh mới](#t%C3%B4i-%C4%91%C3%A3-t%E1%BA%A1o-commit-l%C3%AAn-main-thay-v%C3%AC-m%E1%BB%99t-nh%C3%A1nh-m%E1%BB%9Bi)\n    - [Tôi muốn giữ toàn bộ file từ một ref-ish khác](#t%C3%B4i-mu%E1%BB%91n-gi%E1%BB%AF-to%C3%A0n-b%E1%BB%99-file-t%E1%BB%AB-m%E1%BB%99t-ref-ish-kh%C3%A1c)\n    - [Tôi đã thực hiện một số commit trên một nhánh mặc dù chúng nên ở các nhánh khác nhau](#t%C3%B4i-%C4%91%C3%A3-th%E1%BB%B1c-hi%E1%BB%87n-m%E1%BB%99t-s%E1%BB%91-commit-tr%C3%AAn-m%E1%BB%99t-nh%C3%A1nh-m%E1%BA%B7c-d%C3%B9-ch%C3%BAng-n%C3%AAn-%E1%BB%9F-c%C3%A1c-nh%C3%A1nh-kh%C3%A1c-nhau)\n    - [Tôi muốn xóa các nhánh local đã bị xóa tại luồng trước (upstream)](#t%C3%B4i-mu%E1%BB%91n-x%C3%B3a-c%C3%A1c-nh%C3%A1nh-local-%C4%91%C3%A3-b%E1%BB%8B-x%C3%B3a-t%E1%BA%A1i-lu%E1%BB%93ng-tr%C6%B0%E1%BB%9Bc-upstream)\n    - [Tôi vô tình xóa nhánh của tôi](#t%C3%B4i-v%C3%B4-t%C3%ACnh-x%C3%B3a-nh%C3%A1nh-c%E1%BB%A7a-t%C3%B4i)\n    - [Tôi muốn xoá một nhánh](#t%C3%B4i-mu%E1%BB%91n-xo%C3%A1-m%E1%BB%99t-nh%C3%A1nh)\n    - [Tôi muốn xoá nhiều nhánh](#t%C3%B4i-mu%E1%BB%91n-xo%C3%A1-nhi%E1%BB%81u-nh%C3%A1nh)\n    - [Tôi muốn đổi tên một nhánh](#t%C3%B4i-mu%E1%BB%91n-%C4%91%E1%BB%95i-t%C3%AAn-m%E1%BB%99t-nh%C3%A1nh)\n    - [Tôi muốn checkout đến một nhánh remote mà người khác đang làm việc trên đó](#t%C3%B4i-mu%E1%BB%91n-checkout-%C4%91%E1%BA%BFn-m%E1%BB%99t-nh%C3%A1nh-remote-m%C3%A0-ng%C6%B0%E1%BB%9Di-kh%C3%A1c-%C4%91ang-l%C3%A0m-vi%E1%BB%87c-tr%C3%AAn-%C4%91%C3%B3)\n    - [Tôi muốn tạo một nhánh remote mới từ một nhánh local hiện tại](#t%C3%B4i-mu%E1%BB%91n-t%E1%BA%A1o-m%E1%BB%99t-nh%C3%A1nh-remote-m%E1%BB%9Bi-t%E1%BB%AB-m%E1%BB%99t-nh%C3%A1nh-local-hi%E1%BB%87n-t%E1%BA%A1i)\n    - [Tôi muốn thiết lập một nhánh remote làm upstream (luồng trước) cho một nhánh local](#t%C3%B4i-mu%E1%BB%91n-thi%E1%BA%BFt-l%E1%BA%ADp-m%E1%BB%99t-nh%C3%A1nh-remote-l%C3%A0m-upstream-lu%E1%BB%93ng-tr%C6%B0%E1%BB%9Bc-cho-m%E1%BB%99t-nh%C3%A1nh-local)\n    - [Tôi muốn để HEAD của tôi dõi theo nhánh mặc định của remote](#t%C3%B4i-mu%E1%BB%91n-%C4%91%E1%BB%83-head-c%E1%BB%A7a-t%C3%B4i-d%C3%B5i-theo-nh%C3%A1nh-m%E1%BA%B7c-%C4%91%E1%BB%8Bnh-c%E1%BB%A7a-remote)\n    - [Tôi đã thực hiện thay đổi trên sai nhánh](#t%C3%B4i-%C4%91%C3%A3-th%E1%BB%B1c-hi%E1%BB%87n-thay-%C4%91%E1%BB%95i-tr%C3%AAn-sai-nh%C3%A1nh)\n    - [Tôi muốn tách một nhánh thành hai](#t%C3%B4i-mu%E1%BB%91n-t%C3%A1ch-m%E1%BB%99t-nh%C3%A1nh-th%C3%A0nh-hai)\n  - [Rebasing và Merging](#rebasing-v%C3%A0-merging)\n    - [Tôi muốn đảo ngược rebase/merge](#t%C3%B4i-mu%E1%BB%91n-%C4%91%E1%BA%A3o-ng%C6%B0%E1%BB%A3c-rebasemerge)\n    - [Tôi đã rebase, nhưng tôi không muốn push ép (force push)](#t%C3%B4i-%C4%91%C3%A3-rebase-nh%C6%B0ng-t%C3%B4i-kh%C3%B4ng-mu%E1%BB%91n-push-%C3%A9p-force-push)\n    - [Tôi cần kết hợp các commit](#t%C3%B4i-c%E1%BA%A7n-k%E1%BA%BFt-h%E1%BB%A3p-c%C3%A1c-commit)\n      - [Chiến lược merge an toàn](#chi%E1%BA%BFn-l%C6%B0%E1%BB%A3c-merge-an-to%C3%A0n)\n      - [Tôi cần merge một nhánh thành một commit duy nhất](#t%C3%B4i-c%E1%BA%A7n-merge-m%E1%BB%99t-nh%C3%A1nh-th%C3%A0nh-m%E1%BB%99t-commit-duy-nh%E1%BA%A5t)\n      - [Tôi chỉ muốn kết hợp các commit chưa push](#t%C3%B4i-ch%E1%BB%89-mu%E1%BB%91n-k%E1%BA%BFt-h%E1%BB%A3p-c%C3%A1c-commit-ch%C6%B0a-push)\n      - [Tôi cần huỷ bỏ merge](#t%C3%B4i-c%E1%BA%A7n-hu%E1%BB%B7-b%E1%BB%8F-merge)\n    - [Tôi cần cập nhật commit gốc (parent commit) cho nhánh của tôi](#t%C3%B4i-c%E1%BA%A7n-c%E1%BA%ADp-nh%E1%BA%ADt-commit-g%E1%BB%91c-parent-commit-cho-nh%C3%A1nh-c%E1%BB%A7a-t%C3%B4i)\n    - [Kiểm tra xem tất cả commit trên một nhánh đã được merge](#ki%E1%BB%83m-tra-xem-t%E1%BA%A5t-c%E1%BA%A3-commit-tr%C3%AAn-m%E1%BB%99t-nh%C3%A1nh-%C4%91%C3%A3-%C4%91%C6%B0%E1%BB%A3c-merge)\n    - [Các vấn đề có thể xảy ra với interactive rebase](#c%C3%A1c-v%E1%BA%A5n-%C4%91%E1%BB%81-c%C3%B3-th%E1%BB%83-x%E1%BA%A3y-ra-v%E1%BB%9Bi-interactive-rebase)\n      - [Màn hình chỉnh sửa rebase ghi 'noop'](#m%C3%A0n-h%C3%ACnh-ch%E1%BB%89nh-s%E1%BB%ADa-rebase-ghi-noop)\n      - [Có một vài xung đột](#c%C3%B3-m%E1%BB%99t-v%C3%A0i-xung-%C4%91%E1%BB%99t)\n  - [Stash (Cất)](#stash-c%E1%BA%A5t)\n    - [Stash tất cả chỉnh sửa](#stash-t%E1%BA%A5t-c%E1%BA%A3-ch%E1%BB%89nh-s%E1%BB%ADa)\n    - [Stash các file cụ thể](#stash-c%C3%A1c-file-c%E1%BB%A5-th%E1%BB%83)\n    - [Stash với message (thông điệp)](#stash-v%E1%BB%9Bi-message-th%C3%B4ng-%C4%91i%E1%BB%87p)\n    - [Apply một stash cụ thể từ danh sách](#apply-m%E1%BB%99t-stash-c%E1%BB%A5-th%E1%BB%83-t%E1%BB%AB-danh-s%C3%A1ch)\n    - [Stash trong khi giữ các thay đổi chưa stage](#stash-trong-khi-gi%E1%BB%AF-c%C3%A1c-thay-%C4%91%E1%BB%95i-ch%C6%B0a-stage)\n  - [Finding (Tìm)](#finding-t%C3%ACm)\n    - [Tôi muốn tìm một chuỗi ký tự trong bất kỳ commit nào](#t%C3%B4i-mu%E1%BB%91n-t%C3%ACm-m%E1%BB%99t-chu%E1%BB%97i-k%C3%BD-t%E1%BB%B1-trong-b%E1%BA%A5t-k%E1%BB%B3-commit-n%C3%A0o)\n    - [Tôi muốn tìm tác giả hoặc người commit](#t%C3%B4i-mu%E1%BB%91n-t%C3%ACm-t%C3%A1c-gi%E1%BA%A3-ho%E1%BA%B7c-ng%C6%B0%E1%BB%9Di-commit)\n    - [Tôi muốn liệt kê các commit chứa các file cụ thể](#t%C3%B4i-mu%E1%BB%91n-li%E1%BB%87t-k%C3%AA-c%C3%A1c-commit-ch%E1%BB%A9a-c%C3%A1c-file-c%E1%BB%A5-th%E1%BB%83)\n    - [Tôi muốn xem lịch sử commit của một function (chức năng) cụ thể](#t%C3%B4i-mu%E1%BB%91n-xem-l%E1%BB%8Bch-s%E1%BB%AD-commit-c%E1%BB%A7a-m%E1%BB%99t-function-ch%E1%BB%A9c-n%C4%83ng-c%E1%BB%A5-th%E1%BB%83)\n    - [Tìm một tag mà một commit đã tham chiếu](#t%C3%ACm-m%E1%BB%99t-tag-m%C3%A0-m%E1%BB%99t-commit-%C4%91%C3%A3-tham-chi%E1%BA%BFu)\n  - [Submodules](#submodules)\n    - [Clone tất cả submodules](#clone-t%E1%BA%A5t-c%E1%BA%A3-submodules)\n    - [Xoá một submodule](#xo%C3%A1-m%E1%BB%99t-submodule)\n  - [Miscellaneous Objects (Những thứ khác)](#miscellaneous-objects-nh%E1%BB%AFng-th%E1%BB%A9-kh%C3%A1c)\n    - [Copy thư mục hoặc tệp file từ một nhánh sang nhánh khác](#copy-th%C6%B0-m%E1%BB%A5c-ho%E1%BA%B7c-t%E1%BB%87p-file-t%E1%BB%AB-m%E1%BB%99t-nh%C3%A1nh-sang-nh%C3%A1nh-kh%C3%A1c)\n    - [Khôi phục một file đã bị xoá](#kh%C3%B4i-ph%E1%BB%A5c-m%E1%BB%99t-file-%C4%91%C3%A3-b%E1%BB%8B-xo%C3%A1)\n    - [Xoá tag](#xo%C3%A1-tag)\n    - [Khôi phục một tag đã bị xoá](#kh%C3%B4i-ph%E1%BB%A5c-m%E1%BB%99t-tag-%C4%91%C3%A3-b%E1%BB%8B-xo%C3%A1)\n    - [Patch (Vá) bị xóa](#patch-v%C3%A1-b%E1%BB%8B-x%C3%B3a)\n    - [Xuất một repository ra một file Zip](#xu%E1%BA%A5t-m%E1%BB%99t-repository-ra-m%E1%BB%99t-file-zip)\n    - [Push một nhánh và một tag có tên giống nhau](#push-m%E1%BB%99t-nh%C3%A1nh-v%C3%A0-m%E1%BB%99t-tag-c%C3%B3-t%C3%AAn-gi%E1%BB%91ng-nhau)\n  - [Tracking (Theo dõi) các file](#tracking-theo-d%C3%B5i-c%C3%A1c-file)\n    - [Tôi muốn thay đổi cách viết hoa của tên tệp mà không thay đổi nội dung của tệp](#t%C3%B4i-mu%E1%BB%91n-thay-%C4%91%E1%BB%95i-c%C3%A1ch-vi%E1%BA%BFt-hoa-c%E1%BB%A7a-t%C3%AAn-t%E1%BB%87p-m%C3%A0-kh%C3%B4ng-thay-%C4%91%E1%BB%95i-n%E1%BB%99i-dung-c%E1%BB%A7a-t%E1%BB%87p)\n    - [Tôi muốn ghi đè lên các tệp local khi thực hiện lệnh git pull](#t%C3%B4i-mu%E1%BB%91n-ghi-%C4%91%C3%A8-l%C3%AAn-c%C3%A1c-t%E1%BB%87p-local-khi-th%E1%BB%B1c-hi%E1%BB%87n-l%E1%BB%87nh-git-pull)\n    - [Tôi muốn xóa một tệp khỏi Git nhưng vẫn giữ tệp](#t%C3%B4i-mu%E1%BB%91n-x%C3%B3a-m%E1%BB%99t-t%E1%BB%87p-kh%E1%BB%8Fi-git-nh%C6%B0ng-v%E1%BA%ABn-gi%E1%BB%AF-t%E1%BB%87p)\n    - [Tôi muốn đảo ngược tệp về bản sửa đổi cụ thể](#t%C3%B4i-mu%E1%BB%91n-%C4%91%E1%BA%A3o-ng%C6%B0%E1%BB%A3c-t%E1%BB%87p-v%E1%BB%81-b%E1%BA%A3n-s%E1%BB%ADa-%C4%91%E1%BB%95i-c%E1%BB%A5-th%E1%BB%83)\n    - [Tôi muốn liệt kê các thay đổi của một tệp cụ thể giữa các commit hoặc các nhánh](#t%C3%B4i-mu%E1%BB%91n-li%E1%BB%87t-k%C3%AA-c%C3%A1c-thay-%C4%91%E1%BB%95i-c%E1%BB%A7a-m%E1%BB%99t-t%E1%BB%87p-c%E1%BB%A5-th%E1%BB%83-gi%E1%BB%AFa-c%C3%A1c-commit-ho%E1%BA%B7c-c%C3%A1c-nh%C3%A1nh)\n    - [Tôi muốn Git bỏ qua những thay đổi đối với một tệp cụ thể](#t%C3%B4i-mu%E1%BB%91n-git-b%E1%BB%8F-qua-nh%E1%BB%AFng-thay-%C4%91%E1%BB%95i-%C4%91%E1%BB%91i-v%E1%BB%9Bi-m%E1%BB%99t-t%E1%BB%87p-c%E1%BB%A5-th%E1%BB%83)\n  - [Debugging (Gỡ lỗi) with Git](#debugging-g%E1%BB%A1-l%E1%BB%97i-with-git)\n  - [Cấu hình (Configuration)](#c%E1%BA%A5u-h%C3%ACnh-configuration)\n    - [Tôi muốn thêm bí danh (alias) cho một số lệnh Git](#t%C3%B4i-mu%E1%BB%91n-th%C3%AAm-b%C3%AD-danh-alias-cho-m%E1%BB%99t-s%E1%BB%91-l%E1%BB%87nh-git)\n    - [Tôi muốn thêm một thư mục trống vào repository của tôi](#t%C3%B4i-mu%E1%BB%91n-th%C3%AAm-m%E1%BB%99t-th%C6%B0-m%E1%BB%A5c-tr%E1%BB%91ng-v%C3%A0o-repository-c%E1%BB%A7a-t%C3%B4i)\n    - [Tôi muốn cache (cho vào bộ nhớ đệm) một username và password cho một repository](#t%C3%B4i-mu%E1%BB%91n-cache-cho-v%C3%A0o-b%E1%BB%99-nh%E1%BB%9B-%C4%91%E1%BB%87m-m%E1%BB%99t-username-v%C3%A0-password-cho-m%E1%BB%99t-repository)\n    - [Tôi muốn Git bỏ qua các quyền và thay đổi về filemode (chế độ file)](#t%C3%B4i-mu%E1%BB%91n-git-b%E1%BB%8F-qua-c%C3%A1c-quy%E1%BB%81n-v%C3%A0-thay-%C4%91%E1%BB%95i-v%E1%BB%81-filemode-ch%E1%BA%BF-%C4%91%E1%BB%99-file)\n    - [Tôi muốn đặt người dùng toàn cục (global user)](#t%C3%B4i-mu%E1%BB%91n-%C4%91%E1%BA%B7t-ng%C6%B0%E1%BB%9Di-d%C3%B9ng-to%C3%A0n-c%E1%BB%A5c-global-user)\n  - [Tôi không biết mình đã làm gì sai](#t%C3%B4i-kh%C3%B4ng-bi%E1%BA%BFt-m%C3%ACnh-%C4%91%C3%A3-l%C3%A0m-g%C3%AC-sai)\n  - [Git Shortcuts (phím tắt)](#git-shortcuts-ph%C3%ADm-t%E1%BA%AFt)\n    - [Git Bash](#git-bash)\n    - [PowerShell trên Windows](#powershell-tr%C3%AAn-windows)\n- [Tài nguyên khác](#t%C3%A0i-nguy%C3%AAn-kh%C3%A1c)\n  - [Sách](#s%C3%A1ch)\n  - [Hướng dẫn](#h%C6%B0%E1%BB%9Bng-d%E1%BA%ABn)\n  - [Scripts (tập lệnh) và các công cụ](#scripts-t%E1%BA%ADp-l%E1%BB%87nh-v%C3%A0-c%C3%A1c-c%C3%B4ng-c%E1%BB%A5)\n  - [GUI Clients](#gui-clients)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n## Repositories (Kho)\n\n### Tôi muốn tạo một repository trên local\n\nĐể tạo một Git repository tại thư mục đã tồn tại:\n\n```sh\n(thư-mục-của-tôi) $ git init\n```\n\n### Tôi muốn clone một remote repository\n\nĐể clone (copy) một remote repository, copy đường dẫn url cho repository, và chạy :\n\n```sh\n$ git clone [url]\n```\n\nLệnh này sẽ tải xuống một thư mục có tên giống tên của remote repository. Hãy chắc chắn rằng bạn có kết nối đến remote server khi bạn đang clone về (phần lớn thời gian nghĩa là cần đảm bảo bạn kết nối được với internet).\n\nĐể clone vào một thư mục với tên khác với tên mặc định của repository:\n\n```sh\n$ git clone [url] name-of-new-folder\n```\n\n### Tôi để sai remote repository\n\nCó thể có vài vấn đề khác nhau:\n\nNếu bạn clone sai repository, chỉ cần xóa thư mục tạo bởi `git clone` và sau đó clone đúng remote repository.\n\nNếu bạn để nhầm repository là origin của một local repository hiện tại, thay đổi URL của origin với lệnh:\n\n```sh\n$ git remote set-url origin [url của repo đúng]\n```\n\nXem thêm tại [StackOverflow](https://stackoverflow.com/questions/2432764/how-to-change-the-uri-url-for-a-remote-git-repository#2432799).\n\n\n### Tôi muốn thêm sửa code cho repository của người khác\n\nGit không cho bạn thêm sửa code vào repository của người khác nếu không có quyền truy cập. GitHub cũng thế, GitHub khác với Git vì là dịch vụ hosting cho các Git repository. Nhưng bạn có thể  thêm sửa code với các patch vá lỗi, hoặc, nếu trên GitHub, với forks và pull requests.\n\nTrước hêt, một vài điều về fork. Một fork là một copy của một repository. Đây không phải là một lệnh git, mà là một hành động thường thấy trên GitHub, Bitbucket, GitLab — hoặc bắt cứ đâu host các Git repository. Bạn có thể fork một repository qua UI của dịch vụ host.\n\n#### Thêm sửa code với pull requests\n\nSau khi đã fork một repository, bạn thường phải clone repository về máy của bạn. Tất nhiên bạn có thể tạo vài chỉnh sửa nhỏ trên GitHub nếu không clone về máy, nhưng văn bản này không phải là github-flight-rules, thế nên hãy xem cách trên máy local.\n\n```sh\n# nếu bạn dùng ssh\n$ git clone git@github.com:k88hudson/git-flight-rules.git\n\n# nếu bạn dùng https\n$ git clone https://github.com/k88hudson/git-flight-rules.git\n```\n\nNếu bạn `cd` vào thư mục được tạo, và chạy lệnh `git remote`, bạn sẽ thấy danh sách các remote. Thường sẽ có một remote - `origin` - trỏ đến `k88hudson/git-flight-rules`. Trong trường hợp này, bạn cũng muốn một remote trỏ đến fork của bạn.\n\nĐầu tiên, để theo quy chuẩn dùng Git, chúng ta sẽ dùng remote tên `origin` cho repository của bạn và tên `upstream` cho repository mà bạn fork. Để đổi tên cho remote `origin` sang tên `upstream` chạy lệnh:\n\n```sh\n$ git remote rename origin upstream\n```\n\nBạn cũng có thể đổi tên với lệnh `git remote set-url`, nhưng sẽ mất thêm thời gian và nhiều bước hơn.\n\nSau đó, tạo remote mới để trỏ về repository của bạn.\n\n```sh\n$ git remote add origin git@github.com:YourtGitHubUsername/git-flight-rules.git\n```\n\nLưu ý là bây giờ bạn có hai remote.\n\n- `origin` trỏ đến repository của bạn.\n- `upstream` trỏ đến repository nguyên bản  .\n\nVới `origin`, bạn có thể đọc và viết. Với `upstream`, bạn chỉ có thể đọc.\n\nSau khi đã chỉnh sửa theo mong muốn, push (đẩy) các thay đổi (thường là ở trong branch) tới remote tên `origin`. Nếu bạn ở trên nhánh, bạn có thể dùng `--set-upstream` để tránh cần phải ghi rõ dùng brach nào của remote mỗi lần push trong tương lai khi dùng nhánh đấy. Ví dụ:\n\n```sh\n$ (feature/my-feature) git push --set-upstream origin feature/my-feature\n```\n\nKhông có cách nào để tạo pull request trên giao diện lệnh (CLI) với Git (mặc dù có vài công cụ, như [hub](http://github.com/github/hub), có cho bạn lựa chọn này). Nếu bạn sãn sàng tạo Pull Request, trở lại GitHub (hoặc dịch vụ host Git) và tạo pull request mới. Nhớ là dịch vụ host sẽ tự động link repository nguyên bản và repository do fork.\n\nSau cùng, nhớ đùng quên trả lời những comment phê duyệt code.\n\n#### Thêm sửa code với các patch (vá)\n\nMột cách khác để thêm sửa code mà không cần sử dụng dịch vụ bên thứ ba như GitHub là dùng `git format-patch`.\n\n`format-patch` tạo file (tệp) dạng .patch  cho một hoặc nhiều commit. File này là cơ bản là danh sách nhưng thay đổi, giống như những commit diffs bạn xem được trên Github.\n\nCác patch có thể được xem hoặc thậm chí thêm sửa bởi người nhận và áp gắn với lệnh `git am`.\n\nVí dụ, để tạo patch dựa vào commit mới nhât, bạn chạy lệnh `git format-patch HEAD^`, lệnh sẽ tạo một tệp .patch với tên như: `0001-My-Commit-Message.patch`.\n\nĐể áp gắn tệp patch cho repository, bạn sẽ dùng lệnh `git am ./0001-My-Commit-Message.patch`.\n\nCác patch còn có thể gửi qua email với lệnh `git send-email`. Để xem thêm thông tin về cách dùng hoặc cấu hình, xem: https://git-send-email.io\n\n#### Tôi cần update fork của tôi với những thay đổi mới nhất từ repository nguyên bản\n\nSau một quãng thời gian, kho `upstream` có thể có thêm thay đổi, và những thay đổi này cần phải được tải về  kho `origin`. Nhớ là giống bạn, những người khác cũng đang góp sức của họ. Giả dụ bạn đang ở nhánh cho tính năng mới bạn đang thiết kế, và bạn cần update nhánh với những thay đổi trên repository nguyên bản.\n\nCó khi bạn đã có remote trỏ đến project nguyên bản. Nếu không, hãy tạo nó. Thường chúng ta dùng tên `upstream` cho remote này:\n\n```sh\n$ (main) git remote add upstream <link-tới-repository-nguyên-bản>\n# $ (main) git remote add upstream git@github.com:k88hudson/git-flight-rules.git\n```\n\nBây giờ bạn fetch (lấy) từ `upstream` và nhận những update mới nhất.\n\n```sh\n$ (main) git fetch upstream\n$ (main) git merge upstream/main\n\n# hoặc với một lệnh duy nhất\n$ (main) git pull upstream main\n```\n\n## Chỉnh sửa Commit\n\n<a name=\"diff-last\"></a>\n### Tôi vừa commit cái gì?\n\nGiả sử bạn vừa commit những thay đổi một cách mù quáng với lệnh `git commit -a` và bạn không chắc chắn nội dung thực sự của commit vừa thực hiện là gì. Bạn có thể hiển thị ra commit gần nhất trên trỏ HEAD hiện tại của bạn với lệnh:\n\n```sh\n(main)$ git show\n```\n\nHoặc\n\n```sh\n$ git log -n1 -p\n```\n\nNếu bạn muốn xem một file tại một commit cụ thể, bạn cũng có thể làm được điều này (khi `<commitid>`  là commit mà bạn muốn biết) với lệnh:\n\n```sh\n$ git show <commitid>:filename\n```\n\n<a name=\"wrong-thing-in-commit-message\"></a>\n### Tôi đã viết sai vài thứ trong message (thông điệp) của commit\n\nNếu bạn đã viết sai thứ gì đó và commit chưa được push lên, bạn có thể làm theo cách sau để thay đổi message của commit mà không làm thay đổi commit:\n\n```sh\n$ git commit --amend --only\n```\n\nCâu lệnh đó sẽ mở trình soạn thảo (text editor) mặc định của bạn, nơi bạn có thể chỉnh sửa message. Ngoài ra, bạn có thể làm tất cả điều này với lệnh sau:\n\n```sh\n$ git commit --amend --only -m 'xxxxxxx'\n```\n\nNếu bạn đã đẩy message lên, bạn có thể chỉnh sửa commit và force push (đẩy ép), nhưng cách này không được khuyến khích.\n\n<a name=\"commit-wrong-author\"></a>\n### Tôi đã commit với cấu hình tên và email sai\n\nNếu đó là một commit độc lập, chỉnh sửa nó:\n\n```sh\n$ git commit --amend --no-edit --author \"TênTácGiảMới <authoremail@mydomain.com>\"\n```\n\nMột cách khác để cấu hình đúng tác giả là cài đặt lại với lệnh `git config --global author.(name|email)` và sau đó chạy lệnh\n\n```sh\n$ git commit --amend --reset-author --no-edit\n```\n\nNếu bạn cần thay đổi tất cả lịch sử, hãy xem trang `man` của `git filter-branch`.\n\n### Tôi muốn xoá một file từ commit trước\n\nĐể xoá các thay đổi đối với một file khỏi commit trước, hãy làm như sau:\n\n```sh\n$ git checkout HEAD^ myfile\n$ git add myfile\n$ git commit --amend --no-edit\n```\n\nTrong trường hợp file mới được thêm vào commit và bạn muốn xoá nó (riêng trên Git), hãy thực hiện:\n\n```sh\n$ git rm --cached myfile\n$ git commit --amend --no-edit\n```\n\nCách này đăc biệt hữu ích khi bạn đang mở một bản patch và bạn đã commit một file không cần thiết và cần force push để cập nhật bản patch trên remote. Dòng `--no-edit` được dùng để giữ không thay đổi message cho commit hiện tại.\n\n<a name=\"delete-pushed-commit\"></a>\n### Tôi muốn chuyển một thay đổi từ commit sang commit khác\nNếu bạn đã thực hiện một commit bao gồm các thay đổi phù hợp hơn với một commit khác, bạn có thể di chuyển các thay đổi sang commit khác bằng cách sử dụng rebase tương tác (interactive rebase). Đó là câu trả lời từ [stackoverflow](https://stackoverflow.com/a/54985304/2491502).\n\nVí dụ: bạn có ba commit (a, b, c). Trên b, bạn đã thay đổi file1 và file2 và bạn muốn chuyển thay đổi trên file1 từ commit b sang commit a.\n\nĐầu tiên, rebase interactively:\n\n```sh\n$ git rebase -i HEAD~3\n```\n\nEditor sẽ hiện lên như bên dưới:\n\n```sh\npick a\npick b\npick c\n```\n\nSửa 2 dòng với a và b thành edit:\n\n```sh\nedit a\nedit b\npick c\n```\n\nLưu và đóng Editor. Bạn sẽ được đưa tới commit b. Bây giờ, hãy reset các thay đổi của file1:\n\n```sh\n$ git reset HEAD~1 file1\n```\n\nThao tác trên sẽ unstash những thay đổi trong file1. Tiếp tục, stash những thay đổi đó và tiếp tục rebase:\n\n```sh\n$ git stash\n$ git rebase --continue\n```\n\nBây giờ bạn sẽ quay lại chỉnh sửa commit a. Unstash các thay đổi sau đó thêm chúng vào commit hiện tại và tiếp tục rebase:\n\n```sh\n$ git stash pop\n$ git add file1\n$ git commit --amend --no-edit\n$ git rebase --continue\n```\n\nBây giờ quá trình rebase của bạn đã hoàn tất, với những thay đổi từ b trên a. Nếu bạn muốn di chuyển các thay đổi từ b sang c, bạn sẽ phải thực hiện hai lần rebase vì c đứng trước b: một để lấy các thay đổi ra khỏi b, sau đó một để chỉnh sửa c và thêm các thay đổi đã stash.\n\n<a name=\"delete-pushed-commit\"></a>\n### Tôi muốn xoá hoặc loại bỏ commit mới nhất\n\nNếu bạn muốn xoá các commit đã push, bạn có thể làm như sau. Tuy nhiên, cách này sẽ thay đổi lịch sử  commit không thay đổi được và làm hỏng lịch sử của bất kỳ ai khác đã pull từ repository. Tóm lại, nếu bạn không chắc chắn, bạn không bao giờ nên làm cách này.\n\n```sh\n$ git reset HEAD^ --hard\n$ git push --force-with-lease [remote] [branch]\n```\n\nNếu bạn chưa push, để  đảo ngược Git về trạng thái trước khi bạn thực hiện commit mới nhất (trong khi vãn giữ các thay đổi trong stage) hãy chạy lệnh:\n\n```\n(my-branch)$ git reset --soft HEAD^\n```\n\nCách này chỉ phù hợp nếu bạn chưa push. Nếu bạn đã push, điều thực sự an toàn nhất cần làm là `git revert SHAcủaCommitSai`. Lệnh này sẽ tạo một commit mới để quay trở lại thay đổi của commit trước đó. Hoặc nếu nhánh bạn đã push là rebase-safe (không có kỳ vọng các dev khác sẽ pull từ nó), bạn chỉ có thể sử dụng `git push --force-with-lease`. Để biết thêm, hãy xem [phần trên](#delete-pushed-commit).\n\n<a name=\"delete-any-commit\"></a>\n### Xoá/loại bỏ bất kỳ commit nào\n\nLưu ý như trên. Không bao giờ làm điều này nếu có thể tránh được.\n\n```sh\n$ git rebase --onto SHA1_OF_BAD_COMMIT^ SHA1_OF_BAD_COMMIT\n$ git push --force-with-lease [remote] [branch]\n```\n\nHoặc thực hiện một [interactive rebase](#interactive-rebase) và loại bỏ các dòng tương ứng với các commit bạn muốn loại bỏ.\n\n<a name=\"force-push\"></a>\n### Tôi đã cố gắng push commit đã sửa đổi lên remote, nhưng tôi gặp thông báo lỗi\n\n```sh\nTo https://github.com/yourusername/repo.git\n! [rejected]        mybranch -> mybranch (non-fast-forward)\nerror: failed to push some refs to 'https://github.com/tanay1337/webmaker.org.git'\nhint: Updates were rejected because the tip of your current branch is behind\nhint: its remote counterpart. Integrate the remote changes (e.g.\nhint: 'git pull ...') before pushing again.\nhint: See the 'Note about fast-forwards' in 'git push --help' for details.\n```\n\nLưu ý rằng, như với rebase (xem bên dưới), amend **thay thế commit cũ với một commit mới**, nên bạn phải force push (`--force-with-lease`) các thay đổi của bạn nếu bạn đã push commit trước amend lên remote của bạn. Hãy cẩn thận khi bạn cách này &ndash; *luôn luôn* đảm bảo rằng bạn đã chỉ định một nhánh!\n\n```sh\n(my-branch)$ git push origin mybranch --force-with-lease\n```\n\nNói chung, **tránh force push**. Tốt nhất là tạo và push một commit mới thay vì force-push commit đã sửa đổi vì nó sẽ gây xung đột trong lịch sử commit cho bất kỳ developer nào đã tương tác với nhánh được đề cập hoặc bất kỳ nhánh con nào. `--force-with-lease` sẽ vẫn fail, nếu ai khác cũng đang làm việc trên cùng một nhánh với bạn và việc push lên sẽ ép trên những thay đổi đó.\n\nNếu bạn *hoàn toàn chắc chắn* rằng không ai đang làm việc trên cùng một nhánh hoặc bạn muốn cập nhật đỉnh nhánh (tip of branch) *vô điều kiện*, bạn có thể sử dụng `--force` (`-f`), nhưng cách này nói chung nên tránh.\n\n<a name=\"undo-git-reset-hard\"></a>\n### Tôi đã vô tình thực hiện hard reset và tôi muốn các thay đổi của tôi.\n\nNếu vô tình bạn thực hiện `git reset --hard`, bạn có thể vẫn phục hồi lại được commit của bạn, vì git giữ một bản log cho tất cả mọi thứ trong vài ngày.\n\nChú ý: Điều này chỉ hợp lệ nếu đã có sao lưu, tức là đã có commit hoặc được `stash`. Lệnh `git reset --hard` *sẽ loại bỏ* các thay đổi chưa được commit, vì vậy hãy sử dụng nó một cách thận trọng. (Một lựa chọn an toàn là `git reset --keep`.)\n\n```sh\n(main)$ git reflog\n```\n\nBạn sẽ thấy danh sách các commit gần đây và một commit để reset. Chọn SHA của commit bạn muốn trở lại tới và reset lại:\n\n```sh\n(main)$ git reset --hard SHA1234\n```\n\nThế này là xong.\n\n<a name=\"undo-a-commit-merge\"></a>\n### Tôi vô tình commit và đẩy lên một merge\n\nNếu bạn vô tình merge một nhánh tính năng mới vào nhánh phát triển chính trước khi sẵn sàng để merge, bạn vẫn có thể đảo ngược merge. Nhưng có một điểm phải nắm được: Một commit merge có một hoặc nhiều hơn một parent (gốc) (thường là 2).\n\nLệnh để chạy:\n```sh\n(feature-branch)$ git revert -m 1 <commit>\n```\nDòng `-m 1` là để cho biết cần chọn parent thứ nhất` (nhánh mà merge được thực hiện) làm parent để đảo ngược lại.\n\nChú ý: Số parent không phải là số commit. Thay vào đó, một commit merge sẽ có một dòng như `Merge: 8e2ce2d 86ac2e7`. Số parent là số số nhận dạng đầu-1 (1-based index) của dòng nay, số nhận dạng đầu tiên là 1 cho parent thứ nhất, thứ 2 là cho parent 2, và tiếp tục như thế.\n\n<a name=\"undo-sensitive-commit-push\"></a>\n### Tôi vô tình commit và đẩy các file chứa dữ liệu nhảy cảm\n\nNếu bạn vô tình push lên các file chứa dữ liệu nhạy cảm (mật khẩu, keys, etc.), bạn có thể amend commit trước. Lưu ý rằng khi bạn đã đẩy một commit, bạn nên coi bất kỳ dữ liệu nào đã bị đẩy như đã bị lộ. Các bước này có thể xoá dữ liệu nhạy cảm từ repo công khai (public repo) hoặc bản sao nội bộ, nhưng bạn *không thể* xóa dữ liệu nhạy cảm khỏi các bản sao đã được tải về bởi người khác. Nếu bạn có commit mật khẩu, *hãy thay đổi mật khẩu ngay lập tức*. Nếu bạn đã commit một key, *hãy tạo lại key đó ngay lập tức*. Việc amend commit đã đẩy là không đủ, vì bất kỳ ai cũng có thể đã pull commit chứa dữ liệu nhạy cảm của bạn trong thời gian đấy.\n\nNếu bạn đã chỉnh sửa tệp và xóa dữ liệu nhạy cảm, hãy chạy\n```sh\n(feature-branch)$ git add EditedFile\n(feature-branch)$ git commit --amend --no-edit\n(feature-branch)$ git push --force-with-lease origin [branch]\n```\n\nNếu bạn muốn xóa toàn bộ tệp (nhưng giữ trên local), hãy chạy:\n```sh\n(feature-branch)$ git rm --cached sensitive_file\necho sensitive_file >> .gitignore\n(feature-branch)$ git add .gitignore\n(feature-branch)$ git commit --amend --no-edit\n(feature-branch)$ git push --force-with-lease origin [branch]\n```\nNgoài ra, lưu trữ dữ liệu nhạy cảm của bạn trong các biến môi trường (variable) của local.\n\nNếu bạn muốn xóa hoàn toàn toàn bộ tệp (và không giữ tệp tại local), hãy chạy\n\n```sh\n(feature-branch)$ git rm sensitive_file\n(feature-branch)$ git commit --amend --no-edit\n(feature-branch)$ git push --force-with-lease origin [branch]\n```\n\nNếu bạn đã thực hiện các commit khác (tức là dữ liệu nhạy cảm nằm tại commit trước commit mới nhất), bạn sẽ phải rebase.\n\n<a name=\"remove-large-file-in-repo-history\"></a>\n### Tôi muốn xóa file to quá để chưa bao giờ xuất hiện trong lịch sử repository\n\nNếu file bạn muốn xóa cần bảo mật hay là file chưa thông tin nhạy cảm, xem phần [xóa file chứa thông tin nhạy cảm](#undo-sensitive-commit-push).\n\nMặc dù bạn đã xóa một file to hay file không muốn có trong dự án, nó có thể vẫn tồn tại trong lịch sử git (git history) của respository trong thư mục `.git`, và sẽ khiến các lệnh `git clone` tải file không cần thiết.\n\nNhững bước trong phần này sẽ yêu cầu push ép, và viết lại phần nào lịch sử git của repository, thế nên nếu bạn làm việc với những người khác, kiểm tra là những thay đổi của họ đã được đẩy.\n\nCó hai lựa chọn để viết lại lịch sử, sử dụng tính năng sãn có `git-filter-branch` hoặc dùng [`bfg-repo-cleaner`](https://rtyley.github.io/bfg-repo-cleaner/). `bfg` thao tác sạch hơn và nhanh hơn, nhưng đây là phần mềm bên thứ ba và cần có Java. Chúng ta sẽ xem cả hai cách. Bước cuối cùng là push ép thay đổi của bạn, lần này sẽ còn cần chú ý xem xét hơn các push ép bình thường bởi vì một phần không nhỏ lịch sử repository sẽ thay đổi vĩnh viễn. \n\n#### Cách khuyến khích: Sử dụng dịch vụ bên thứ ba bfg\n\nSử dụng bfg-repo-cleaner cần có Java. Tải file dạng .jar cho phần mềm bfg với đường link [này](https://rtyley.github.io/bfg-repo-cleaner/). Ví dụ tại đây sẽ dùng `bfg.jar`, nhưng file bạn tải xuống có thể có thêm số phiên bản như `bfg-1.13.0.jar`.\n\nĐể xóa một file, dùng lệnh:\n\n```sh\n(main)$ git rm path/to/FileToRemove\n(main)$ git commit -m \"Commit removing filetoremove\"\n(main)$ java -jar ~/Downloads/bfg.jar --delete-files FileToRemove\n```\n\nLưu ý là với bfg bạn dùng tển của file chứ không phải đường dẫn đến file.\n\nBạn cũng có thể xóa file dượng theo một khuôn mẫu, ví dụ xóa tất cả file dạng .jpg:\n\n```sh\n(main)$ git rm *.jpg\n(main)$ git commit -m \"Commit removing *.jpg\"\n(main)$ java -jar ~/Downloads/bfg.jar --delete-files *.jpg\n```\n\nVới bfg, the files that exist on your latest commit will not be affected. For example, if you had several large .tga files in your repo, and then in an earlier commit, you deleted a subset of them, this call does not touch files present in the latest commit\n\nLưu ý, nếu bạn thay đổi tên file trong một commit trước, ví dụ: nếu tệp bắt đầu với tên `LargeFileFirstName.mp4` và một commit đổi tên tệp thành `LargeFileSecondName.mp4`, chạy lệnh `java -jar ~/Downloads/bfg.jar --delete-files LargeFileSecondName.mp4` sé không xóa file trong lịch sử git. Hoặc là chạy lệnh `--delete-files` với cả hai tên, hoặc với khuôn mẫu như trên.\n\n#### Cách có sẵn: Sử dụng git-filter-branch\n\n`git-filter-branch` nặng hơn và ít tính năng hơn, nhưng bạn có thể dùng cách này nếu không thể cài hay chạy `bfg`.\n\nTrong lệnh bên dưới, thay `filepattern` với tên file hoặc khuông mẫu, v.d. `*.jpg`. Lệnh này sẽ xóa file theo khuôn mẫu khỏi tất cả lịch sử của tất cả các nhánh. \n\n```sh\n(main)$ git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch filepattern' --prune-empty --tag-name-filter cat -- --all\n```\n\nGiải thích lệnh trên:\n\n`--tag-name-filter cat` khá là nặng, nhưng là cách đơn giản nhất để giữ nguyên các tags cho các commit mới bằng cách sử dụng lệnh `cat`.\n\n`--prune-empty` xóa những commit bây giờ để trống rỗng.\n\n#### Bước cuối: Đẩy lịch sử đã thay đổi của repository\n\nMột khi bạn đã xóa file, kiểm tra thật cẩn thận là bạn không làm hỏng cái gì trong repo - và nếu bạn đã làm hỏng cái gì đó, dễ nhất là clone repo lại và bắt đầu từ đầu.\nĐể kết thúc, bạn có thể dùng chức năng thu hồi rác (garbage collection) để giảm thiểu kích cỡ tệp .git và rồi push ép. c\n```sh\n(main)$ git reflog expire --expire=now --all && git gc --prune=now --aggressive\n(main)$ git push origin --force --tags\n```\n\nVì bạn vừa viết lại toàn bộ lịch sử git repository, lệnh `git push` có thể quá to để thi hành, và gửi lại thông điệp lỗi (error) `“The remote end hung up unexpectedly”`. Nếu việc này xảy ra, bạn có thể thử tăng post buffer của git:\n```sh\n(main)$ git config http.postBuffer 524288000\n(main)$ git push --force\n```\n\nNếu cách này không hiệu quả, bạn sẽ phải push thủ công lịch sử repo từng cục một. Với lệnh bên dưới, dần dần tăng con số cho `<số cục>` đến khi nào lệnh push thành công.\n```sh\n(main)$ git push -u origin HEAD~<số cục>:refs/head/main --force\n```\nMột khi lệnh push thành công, dần dần giảm thiểu `<số cục>` cho đến khi một lệnh `git push` bình thường thành công.\n\n<a name=\"change-content-of-commit-not-my-last\"></a>\n### Tôi cần thay đổi nội dung của một commit nhưng không phải là cái mới nhất\n\nGiả sử bạn đã có vài (v.d. ba) commit và sau nhận ra là bạn quên mất không cho vào một thứ gì đó hợp hơn với commit đầu tiên. Việc này làm phiền bạn vì mặc dù nếu tiếp tục commit bạn sẽ có lịch sử sạch sẽ nhưng commit của bạn không nguyên chất (những thay đổi liên quan với nhau nên ở cùng một commit). Trong trường hợp như vậy, bạn chắc muốn cho thêm những thay đổi liên quan vào commit mong muốn nhưng không muốn những commit sau tiếp cũng phải sửa theo. Trong trường hợp như vây, `git rebase` có thể cứu bạn.\n\nHay xem trường hợp mà bạn muốn thay đổi commit số ba nếu đếm ngược. \n\n```sh\n(nhánh-bạn)$ git rebase -i HEAD~4\n```\n\nLệnh trên đưa bạn vào mode (chế độ) rebase tương tác (interactive rebase), chế độ cho phép bạn edit ba commit mới nhất. Một trình soạn thảo (text editor) sẽ bật lên trông giống như sau:\n\n```sh\npick 9e1d264 commit trước ba\npick 4b6e19a commit trước hai\npick f4037ec commit trước\n```\n\nvà bạn thay/viết thành:\n\n```sh\nedit 9e1d264 commit trước ba\npick 4b6e19a commit trước hai\npick f4037ec commit trước\n```\n\nLệnh này bảo rebase là bạn muốn thay đổi commit trước ba và giữ hai commit kia không thay đổi. Sau đó bạn save (và đóng) trình soạn thảo. Git bây giờ sẽ bắt đầu rebase. Nó dừng lại ở commit bạn để là edit và cho bạn cơ hội thay đổi commit đấy. Bây giờ bạn có thể cho thêm những thay đổi bạn lỡ không cho vào lần đầu. Để làm thế, bạn edit rồi stage những thay đổi đấyNow you can apply the changes which you missed applying when you initially committed that commit. Sau đó bạn chạy lệnh:\n\n```sh\n(your-branch)$ git commit --amend\n```\n\nLệnh bảo Git là cần tạo lại commit, nhưng giữ nguyên thông điệp commit. which tells Git to recreate the commit, but to leave the commit message unedited. Thế là xong phần khó nhất. Cuối cùng là chạy lệnh:\n\n```sh\n(your-branch)$ git rebase --continue\n```\n\nLệnh trên sẽ giải quyết phần còn lại.\n\n## Staging (sân chuyển tiếp)\n\n<a name=\"stage-tracked-files-and-leave-untracked-files\"></a>\n### Tôi muốn nâng lên stage tất cả file đang theo dõi và bỏ qua file không theo dõi\n\n```sh\n$ git add -u\n```\n\n#### Chỉ nâng một phần các file đang theo dõi\n\n```sh\n# Để nâng các file dạng .txt\n$ git add -u *.txt\n\n# Để nang các file trong thu mục src\n$ git add -u src/\n```\n\n<a name=\"add-staged-changes-to-previous-commit\"></a>\n### Tôi cần cho thêm các thay đổi đang trong stage vào commit trước\n\n```sh\n(my-branch*)$ git commit --amend\n```\n\nNếu bạn đã biết bạn không muốn thay đổi thông điệp commit, bạn có thể yêu cầu git sử dụng lại commit message:\n\n```sh\n(my-branch*)$ git commit --amend -C HEAD\n```\n\n<a name=\"commit-partial-new-file\"></a>\n### Tôi muốn stage một phần của một file mới, nhưng không phải toàn bộ file\n\nThông thường, nếu bạn muốn stage một phần của một file, bạn chạy lệnh này:\n\n```sh\n$ git add --patch filename.x\n```\n\nBạn có thể dùng `-p` thay `--patch` cho ngắn. Lệnh này sẽ mở chế độ interactive. Bạn có thể cho thêm `s` để cắt commit - tuy nhiên, nếu là file mới, bạn sẽ không có lựa chọn này. Để thêm một file mới, làm như sau:\n\n```sh\n$ git add -N filename.x\n```\n\nSau đó, bạn sẽ cần sử dụng `e` để thủ công thêm dòng. Chạy lệnh `git diff --cached` hoặc\n`git diff --staged` sẽ cho bạn thấy những dòng bạn đã stage so với những dòng vẫn lưu ở local.\n\n<a name=\"stage-in-two-commits\"></a>\n### Tôi muốn thêm các thay đổi trong một file vào 2 commit khác nhau\n\n`git add` sẽ thêm toàn bộ file vào một commit. `git add -p` sẽ cho vào chế độ tương tác để chọn những thay đổi bạn muốn thêm vào.\n\n<a name=\"selective-unstage-edits\"></a>\n### Tôi cho lên stage quá nhiều thay đổi, và tôi muốn tách ra thành các commit khác nhau\n\n`git reset -p` sẽ mở chế độ patch và hộp thoại để reset. Việc này sẽ giống như với lệnh `git add -p`, ngoại trừ là việc chọn \"yes\" sẽ đưa thay đổi khỏi stage, loại trừ nó khỏi commit tiếp đến.\n\n<a name=\"unstaging-edits-and-staging-the-unstaged\"></a>\n### Tôi muốn cho lên stage các chỉnh sửa chưa được stage và bỏ khỏi stage các chỉnh sửa đã stage\n\nPhần lớn thời gian, bạn nên hạ tất cả các file đã trên stage và chọn lại những file bạn muốn commit.Nhưng giả sử bạn muốn thay các thay đổi lên và hạ stage, bạn có thể tạo một commit tạm thời, nâng lên stage các thay đổi, rồi stash (cất) nó. Sau đó, reset cái commit tạm thời rồi pop cái stage bạn vừa cất.\n\n```sh\n$ git commit -m \"WIP\"\n$ git add . # \".\" sẽ thêm tất cả file chưa theo dõi\n$ git stash\n$ git reset HEAD^\n$ git stash pop --index 0\n```\n\nGHI CHÚ 1: Lý do để dùng `pop` là để giữ nguyên các thay đổi nhất có thể.\nGHI CHÚ 2: Các file đã nâng lên stage sẽ bị hạ nếu không có thêm cờ `--index`. ([Link](https://stackoverflow.com/questions/31595873/git-stash-with-staged-files-does-stash-convert-staged-files-to-unstaged?answertab=active#tab-top) explains why.)\n\n<a name=\"unstage-specific-staged-file\"></a>\n### Tôi muốn unstage 1 file đã stage cụ thể \n\nĐôi khi chúng tôi có một hoặc nhiều tệp vô tình bị stage và những tệp này chưa được commit trước đó. Để loại bỏ chúng:\n\n```sh\n$ git reset -- <filename>\n```\n\nLệnh trên dẫn đến việc unstage tệp và làm cho nó không bị track.\n\n## Hủy bỏ những thay đổi (Discarding changes)\n\n<a name=\"discard-local-uncommitted-changes\"></a>\n### Tôi muốn bỏ các thay đôi chưa trong commit tại local (đã lên hoặc chưa lên stage)\n\nNếu bạn muốn bỏ tất cả các thay đổi đã lên hoặc chưa lên stage tại local của bạn, bạn có thể làm như sau:\n\n```sh\n(my-branch)$ git reset --hard\n# hoặc\n(main)$ git checkout -f\n```\n\nLệnh sau sẽ hạ khỏi stage tất cả thay đổi bạn đã cho lên stage với `git add`:\n\n```sh\n$ git reset\n```\n\nLệnh sau sẽ đảo ngược tất cả các thay đổi chưa commit tại local (nên chạy tại thư mục gốc repo):\n\n```sh\n$ git checkout .\n```\n\nBạn cũng có thể đảo ngược các thay đổi chưa commit cho một file hoặc một thư mục cụ thể:\n\n```sh\n$ git checkout [thư_mục|file.txt]\n```\n\nTuy nhiên, một cách khác để đảo ngược tất cả các thay đổi chưa commit (dài hơn để nhập, nhưng hoạt động từ bất kỳ thư mục con nào):\n\n```sh\n$ git reset --hard HEAD\n```\n\nLệnh trên sẽ xoá tất cả các file chưa được theo dõi(untracked) tại local, do đó, chỉ các file đã được theo dõi bởi git (tracked) còn tồn:\n\n```sh\n$ git clean -fd\n```\n\nThêm cờ `-x` để xoá tất cả các file đã ignore.\n\n### Tôi muốn loại bỏ các thay đổi cụ thể chưa lên stage\n\nKhi bạn muốn loại bỏ một số, nhưng không phải tất cả, các thay đổi trong bản sao làm việc của bạn.\n\nCheckout các thay đổi không mong muốn, giữ các thay đổi tốt.\n\n```sh\n$ git checkout -p\n# Trả lời y đối với những thay đổi bạn không muốn giữ\n```\n\nMột cách khác thì sử dụng `stash` (cất). Cất tất cả các thay đổi tốt, reset bản sao làm việc và apply lại các thay đổi tốt.\n\n```sh\n$ git stash -p\n# Chọn những thay đổi bạn muốn giữ\n$ git reset --hard\n$ git stash pop\n```\n\nNgoài ra, còn cách cất những thay đổi không mong muốn của bạn và sau đó drop stash.\n\n```sh\n$ git stash -p\n# Chọn những thay đổi bạn không muốn giữ\n$ git stash drop\n```\n\n### Tôi muốn loại bỏ các file cụ thể chưa lên stage\n\nKhi bạn muốn loại bỏ một file cụ thể trong bản sao làm việc của bạn.\n\n```sh\n$ git checkout FileCủaTôi\n```\n\nNgoài ra, để loại bỏ nhiều file trong bản sao làm việc của bạn, hãy liệt kê tất cả chúng.\n\n```sh\n$ git checkout FileThứNhất FileThứHai\n```\n\n### Tôi muốn chỉ loại bỏ các thay đổi chưa lên stage tại local\n\nKhi bạn muốn loại bỏ tất cả các thay đổi chưa commit mà chưa stage tại local\n\n```sh\n$ git checkout .\n```\n<a name=\"discard-all-untracked-files\"></a>\n### Tôi muốn loại bỏ tất cả các file chưa được theo dõi (track)\n\nKhi bạn muốn loại bỏ tất cả các file chưa được theo dõi\n\n```sh\n$ git clean -f\n```\n\n<a name=\"unstage-specific-staged-file\"></a>\n\n## Nhánh\n\n### Tôi muốn liệt kê tất cả các nhánh\n\nLiệt kê các nhanh tại local\n\n```sh\n$ git branch\n```\n\nLiệt kê cách nhánh trên remote\n\n```sh\n$ git branch -r\n```\n\nLiệt kê tất cả các nhánh (cả local và remote)\n\n```sh\n$ git branch -a\n```\n\n<a name=\"create-branch-from-commit\"></a>\n### Tạo một nhánh mới từ một commit\n```sh\n$ git checkout -b <nhánh> <SHA1_Của_COMMIT>\n```\n\n<a name=\"pull-wrong-branch\"></a>\n### Tôi đã pull (kéo) từ/vào sai nhánh\n\nĐây là một cơ hội khác để dùng `git reflog` để xem HEAD đã trỏ ở đâu trước khi pull sai.\n\n```sh\n(main)$ git reflog\nab7555f HEAD@{0}: pull origin nhánh-sai: Fast-forward\nc5bc55a HEAD@{1}: checkout: checkout message goes here\n```\n\nChỉ cần reset nhánh của bạn về commit mong muốn:\n\n```sh\n$ git reset --hard c5bc55a\n```\n\nXong.\n\n<a name=\"discard-local-commits\"></a>\n### Tôi muốn loại bỏ các commit tại local để nhánh của tôi giống như nhánh trên server\n\nKiểm tra rằng bạn chưa push các thay đổi của mình đến server.\n\n`git status` sẽ hiển thị số lượng các commit bạn có hơn origin:\n\n```sh\n(my-branch)$ git status\n# On branch my-branch\n# Your branch is ahead of 'origin/my-branch' by 2 commits.\n#   (use \"git push\" to publish your local commits)\n#\n```\n\nMột cách để reset về origin (để có nhánh giống như trên remote) là chạy lệnh:\n\n```sh\n(my-branch)$ git reset --hard origin/my-branch\n```\n\n<a name=\"move-unstaged-edits-to-new-branch\"></a>\n### Tôi muốn chuyển những thay đổi chưa lên stage tới nhánh mới \n\n```sh\n$ git checkout -b my-branch\n```\n\n<a name=\"move-unstaged-edits-to-old-branch\"></a>\n### Tôi muốn chuyển những thay đổi chưa lên stage tới nhánh khác đã tạo\n\n```sh\n$ git stash\n$ git checkout my-branch\n$ git stash pop\n```\n\n<a name=\"commit-wrong-branch\"></a>\n### Tôi đã tạo commit lên main thay vì một nhánh mới\n\nTạo nhánh mới trong khi giữ main:\n\n```sh\n(main)$ git branch my-branch\n```\n\nReset nhánh main đến commit trước đó:\n\n```sh\n(main)$ git reset --hard HEAD^\n```\n\n`HEAD^` là viết tắt của `HEAD^1`. Đây là viết tắt của parent thứ nhất `HEAD`, tương tự `HEAD^2` là viết tắt của parent thứ hai của commit (merge có thể có 2 parent).\n\nChú ý rằng `HEAD^2`  **không** giống như `HEAD~2` (xem [link](http://www.paulboxley.com/blog/2011/06/git-caret-and-tilde) để thêm thông tin).\n\nNgoài ra, nếu bạn không muốn sử dụng `HEAD^`, tìm mã hash của commit mà bạn muốn main trỏ về(`git log` sẽ giúp bạn). Sau đó reset về mã hash đấy. `git push` sẽ đảm bảo rằng thay đổi này sẽ hiện trên remote của bạn.\n\nVí dụ, nếu hash của commit mà nhánh main của bạn đáng ra là `a13b85e`:\n\n```sh\n(main)$ git reset --hard a13b85e\nHEAD is now at a13b85e\n```\n\nCheckout một nhánh mới để tiếp tục làm việc:\n\n```sh\n(main)$ git checkout my-branch\n```\n\n<a name=\"keep-whole-file\"></a>\n### Tôi muốn giữ toàn bộ file từ một ref-ish khác\n\nGiả sử bạn có một cột mũi làm việc (xem Ghi Chú), với hàng trăm thay đổi. Mọi thứ đang hoạt động. Bây giờ, bạn commit vào một nhánh khác để lưu những thay đổi đó:\n\n```sh\n(solution)$ git add -A && git commit -m \"Cho tất cả các thay đổi trong cột mũi làm việc này vào một commit to.\"\n```\n\nKhi bạn muốn đặt nó vào một nhánh (có thể là feature, có thể `develop`), bạn quan tâm đến việc giữ toàn bộ các file. Bạn muốn chia commit lớn của bạn thành những cái nhỏ hơn.\n\nGiả sử bạn có:\n\n  * nhánh `solution`, với giáp pháp bạn phát triển với cột mũi làm việc của bạn. Hơn `develop` một commit.\n  * nhánh `develop`, nơi bạn muốn thêm các thay đổi của bạn.\n\nBạn có thể giải quyết bằng cách mang nội dung thay đổi sang nhánh của bạn:\n\n```sh\n(develop)$ git checkout solution -- file1.txt\n```\n\nLệnh trên sẽ lấy nội dung của tập tin đó trong nhánh `solution` đến nhánh `develop` của bạn:\n\n```sh\n# On branch develop\n# Your branch is up-to-date with 'origin/develop'.\n# Changes to be committed:\n#  (use \"git reset HEAD <file>...\" to unstage)\n#\n#        modified:   file1.txt\n```\n\nSau đó, commit như bình thường.\n\nLưu ý: Cột mũi giải pháp được phát triển để phân tích hoặc giải quyết vấn đề. Các giải pháp này được sử dụng để ước tính và loại bỏ sau khi mọi người hiểu rõ vấn đề. ~ [Wikipedia](https://en.wikipedia.org/wiki/Extreme_programming_practices).\n\n<a name=\"cherry-pick\"></a>\n### Tôi đã thực hiện một số commit trên một nhánh mặc dù chúng nên ở các nhánh khác nhau\n\nGiả sử bạn đang ở trên nhánh main của bạn. Chạy `git log`, bạn thấy bạn đã thực hiện 2 commit:\n\n```sh\n(main)$ git log\n\ncommit e3851e817c451cc36f2e6f3049db528415e3c114\nAuthor: Alex Lee <alexlee@example.com>\nDate:   Tue Jul 22 15:39:27 2014 -0400\n\n    Bug #21 - Added CSRF protection\n\ncommit 5ea51731d150f7ddc4a365437931cd8be3bf3131\nAuthor: Alex Lee <alexlee@example.com>\nDate:   Tue Jul 22 15:39:12 2014 -0400\n\n    Bug #14 - Fixed spacing on title\n\ncommit a13b85e984171c6e2a1729bb061994525f626d14\nAuthor: Aki Rose <akirose@example.com>\nDate:   Tue Jul 21 01:12:48 2014 -0400\n\n    First commit\n```\n\nHãy lưu ý các hash commit của chúng ta cho mỗi bug (lỗi) (`e3851e8` cho #21, `5ea5173` cho #14).\n\nTrước tiên, hãy đặt lại nhánh main của chúng ta về commit chính xác (`a13b85e`):\n\n```sh\n(main)$ git reset --hard a13b85e\nHEAD is now at a13b85e\n```\n\nBây giờ, chúng ta có thể tạo ra một nhánh mới cho lỗi #21 của chúng ta:\n\n```sh\n(main)$ git checkout -b 21\n(21)$\n```\n\nBây giờ, hãy *cherry-pick* commit cho bug #21 trên đầu của nhánh. Nói tóm lại là chúng ta sẽ áp commit đó, và chỉ commit đó, trực tiếp vào đầu của nhánh.\n\n```sh\n(21)$ git cherry-pick e3851e8\n```\n\nTại thời điểm này, có khả năng có thể có xung đột hợp (merge conflicts). Hãy xem phần [**Có một vài xung đột**](#merge-conflict) trong [phần interactive rebasing ở trên](#interactive-rebase) để làm thế nào giải quyết xung đột hợp.\n\nBây giờ chúng ta hãy tạo một nhánh mới cho bug # 14, cũng dựa trên nhánh main:\n\n```sh\n(21)$ git checkout main\n(main)$ git checkout -b 14\n(14)$\n```\n\nVà cuối cùng, hãy cherry-pick commit cho bug #14:\n\n```sh\n(14)$ git cherry-pick 5ea5173\n```\n\n<a name=\"delete-stale-local-branches\"></a>\n### Tôi muốn xóa các nhánh local đã bị xóa tại luồng trước (upstream)\n\nKhi bạn kết hợp (merge) một pull request trên GitHub, nó sẽ cho bạn lựa chọn để xóa nhánh đã được kết hợp trong fork của bạn. Nếu bạn không có kế hoạch tiếp tục làm việc trên nhánh đấy, mọi thứ sẽ sạch hơn nếu xóa các bản sao local của nhánh, do đó bạn không tồn đọng một cách lộn xộn tại bản sao làm việc của bạn với các nhánh cũ.\n\n```sh\n$ git fetch -p upstream\n```\n\nupstream` là remote bạn muốn fetch (gọi) về.\n\n<a name=\"restore-a-deleted-branch\"></a>\n### Tôi vô tình xóa nhánh của tôi\n\nNếu bạn thường xuyên push lên remote, bạn sẽ an toàn phần lớn thời gian. Nhưng đôi khi bạn có thể sẽ xóa các nhánh của bạn. Giả sử chúng ta tạo một nhánh và tạo một tệp mới:\n\n```sh\n(main)$ git checkout -b my-branch\n(my-branch)$ git branch\n(my-branch)$ touch foo.txt\n(my-branch)$ ls\nREADME.md foo.txt\n```\n\nHãy thêm nó và rồi tạo commit.\n\n```sh\n(my-branch)$ git add .\n(my-branch)$ git commit -m 'foo.txt added'\n(my-branch)$ foo.txt added\n 1 files changed, 1 insertions(+)\n create mode 100644 foo.txt\n(my-branch)$ git log\n\ncommit 4e3cd85a670ced7cc17a2b5d8d3d809ac88d5012\nAuthor: siemiatj <siemiatj@example.com>\nDate:   Wed Jul 30 00:34:10 2014 +0200\n\n    foo.txt added\n\ncommit 69204cdf0acbab201619d95ad8295928e7f411d5\nAuthor: Kate Hudson <katehudson@example.com>\nDate:   Tue Jul 29 13:14:46 2014 -0400\n\n    Fixes #6: Force pushing after amending commits\n```\n\nBây giờ chúng ta chuyển lại về main và 'vô tình' xóa nhánh của chúng ta\n\n```sh\n(my-branch)$ git checkout main\nSwitched to branch 'main'\nYour branch is up-to-date with 'origin/main'.\n(main)$ git branch -D my-branch\nDeleted branch my-branch (was 4e3cd85).\n(main)$ echo ôi không,tôi delete nhánh tôi!\nôi không,tôi delete nhánh tôi!\n```\n\nTại thời điểm này, bạn nên làm quen với 'reflog', một logger (ký sử) được nâng cấp. Nó lưu trữ lịch sử của tất cả các hành động trong repo.\n\n```\n(main)$ git reflog\n69204cd HEAD@{0}: checkout: moving from my-branch to main\n4e3cd85 HEAD@{1}: commit: foo.txt added\n69204cd HEAD@{2}: checkout: moving from main to my-branch\n```\n\nNhư bạn có thể thấy chúng ta có số hash của commit từ nhánh đã xóa của chúng ta. Hãy xem liệu chúng ta có thể khôi phục nhánh đã xóa của chúng ta hay không.\n\n```sh\n(main)$ git checkout -b my-branch-help\nSwitched to a new branch 'my-branch-help'\n(my-branch-help)$ git reset --hard 4e3cd85\nHEAD is now at 4e3cd85 foo.txt added\n(my-branch-help)$ ls\nREADME.md foo.txt\n```\n\nVà đấy! Chúng ta đã phục hồi lại được file bị xóa của chúng ta. `git reflog` cũng hữu ích khi rebase tạo sai lầm lớn.\n\n### Tôi muốn xoá một nhánh\n\nĐể xoá một nhánh tại remote:\n\n```sh\n(main)$ git push origin --delete my-branch\n```\n\nBạn cũng có thể chạy :\n\n```sh\n(main)$ git push origin :my-branch\n```\n\nĐể xoá nhánh tại local:\n\n```sh\n(main)$ git branch -d my-branch\n```\n\nĐể xoá một nhánh local *chưa được* merge với nhánh hiện tại hoặc trên upstream (luồng trước):\n\n```sh\n(main)$ git branch -D my-branch\n```\n\n### Tôi muốn xoá nhiều nhánh\n\nGiả sử bạn muốn xoá tất cả các nhánh bắt đầu với `fix/`:\n\n```sh\n(main)$ git branch | grep 'fix/' | xargs git branch -d\n```\n\n### Tôi muốn đổi tên một nhánh\n\nĐể đổi tên nhánh local hiện tại:\n\n```sh\n(main)$ git branch -m tên-mới\n```\n\nĐể đổi tên nhánh local khác:\n\n```sh\n(main)$ git branch -m tên-cũ tên-mới\n```\n\nĐể vừa xóa nhánh `tên-cũ` tại remote và push nhánh `tên-mới` từ local:\n\n```sh\n(main)$ git push origin :tên_cũ tên_mới\n```\n\n<a name=\"working-on-checkout-remote-branch\"></a>\n### Tôi muốn checkout đến một nhánh remote mà người khác đang làm việc trên đó\n\nĐầu tiên, fetch tất cả nhánh từ remote:\n\n```sh\n(main)$ git fetch --all\n```\n\nGiả sử bạn muốn checkout sang `daves` từ remote.\n\n```sh\n(main)$ git checkout --track origin/daves\nBranch daves set up to track remote branch daves from origin.\nSwitched to a new branch 'daves'\n```\n\n(`--track` là viết tắt của `git checkout -b [branch] [remotename]/[branch]`)\n\nLệnh này sẽ cung cấp cho bạn một bản sao tại local của nhánh `daves` và mọi cập nhật đã được push cũng sẽ được hiển thị từ remote.\n\n### Tôi muốn tạo một nhánh remote mới từ một nhánh local hiện tại\n\n```sh\n$ git push <remote> HEAD\n```\n\nNếu bạn cũng muốn đặt nhánh remote là upstream cho nhánh hiện tại, sử dụng:\n\n```sh\n$ git push -u <remote> HEAD\n```\n\nVới chế độ `upstream` và `simple` (mặc định trong Git 2.0) của cấu hình `push.default`, lệnh sau sẽ push nhánh hiện tại lên nhánh remote được đăng ký trước đó với `-u`:\n\n```sh\n$ git push\n```\n\nCác hành vi của các chế độ khác của `git push` được mô tả trong [doc cho `push.default`](https://git-scm.com/docs/git-config#Documentation/git-config.txt-pushdefault).\n\n### Tôi muốn thiết lập một nhánh remote làm upstream (luồng trước) cho một nhánh local\n\nBạn có thể thiết lập một nhánh remote làm upstream cho nhánh local hiện tại bằng cách chạy lệnh:\n\n```sh\n$ git branch --set-upstream-to [remotename]/[branch]\n# hoặc, dùng ký tắt:\n$ git branch -u [remotename]/[branch]\n```\n\nĐể thiết lập nhánh upstream remote cho nhánh local khác:\n\n```sh\n$ git branch -u [remotename]/[branch] [local-branch]\n```\n\n<a name=\"head-to-track-remote-branch\"></a>\n### Tôi muốn để HEAD của tôi dõi theo nhánh mặc định của remote\n\nBằng cách kiểm tra các nhánh remote của bạn, bạn có thể thấy nhánh remote nào mà HEAD của bạn đang theo dõi. Trong một số trường hợp, có thể đấy không phải là nhánh mong muốn.\n\n```sh\n$ git branch -r\n  origin/HEAD -> origin/gh-pages\n  origin/main\n```\n\nĐể thay đổi  `origin/HEAD` sang theo dõi `origin/main`, bạn có thể chạy lệnh này:\n\n```sh\n$ git remote set-head origin --auto\norigin/HEAD set to main\n```\n\n### Tôi đã thực hiện thay đổi trên sai nhánh\n\nBạn đã thực hiện các thay đổi chưa được commit và nhận ra bạn đang ở sai nhánh. Stash (cất) các thay đổi và apply (áp dụng) chúng vào nhánh bạn muốn:\n\n```sh\n(wrong_branch)$ git stash\n(wrong_branch)$ git checkout nhánh_đúng\n(correct_branch)$ git stash apply\n```\n\n<a name=\"split-branch-into-two\"></a>\n### Tôi muốn tách một nhánh thành hai\n\nBạn đã tạo rất nhiều commit trên một nhành và bây giờ bạn muốn tách nhánh ra thành hai, một nhánh kết thúc với một commit cũ, và một nhánh với tất cả các thay đổi.\n\nDùng `git log` để tìm commit bạn muốn làm mốc để tách. Sau đó chạy lệnh như sau:\n\n```sh\n(original_branch)$ git checkout -b new_branch\n(new_branch)$ git checkout original_branch\n(original_branch)$ git reset --hard <số sha1 commit để tách>\n```\n\nNếu bạn trước đó đã push nhánh gốc lên remote, bạn sẽ cần phải push ép (force push). Để thêm thông tin xem [Stack Overlflow](https://stackoverflow.com/questions/28983458/how-to-split-a-branch-in-two-with-git/28983843#28983843).\n\n## Rebasing và Merging\n\n<a name=\"undo-rebase\"></a>\n### Tôi muốn hoàn tác rebase/merge\n\nBạn có thể đã merge hoặc rebase nhánh hiện tại của bạn với một nhánh sai hoặc bạn không thể tìm ra cách hoàn thành quá trình rebase/merge. Git lưu con trỏ original HEAD trong một variable (biến) được gọi là ORIG_HEAD trước khi chạy các hành động nguy hiểm, vì vậy bạn có thể dễ dàng khôi phục lại trạng thái trước khi rebase/merge.\n\n```sh\n(my-branch)$ git reset --hard ORIG_HEAD\n```\n\n<a name=\"force-push-rebase\"></a>\n### Tôi đã rebase, nhưng tôi không muốn push ép (force push)\n\nThật không may, bạn bắt buộc phải push ép, nếu bạn muốn những thay đổi đó được phản ánh trên nhánh remote. Điều này là do bạn đã thay đổi lịch sử. Nhánh remote sẽ không chấp nhận thay đổi trừ khi bạn push ép. Đây là một trong những lý do chính khiến nhiều người sử dụng quy trình làm việc trên merge, thay vì quy trình làm việc trên rebasing - các nhóm lớn có thể gặp rắc rối khi developer push ép. Nên sử dụng rebase một cách thận trọng. Một cách an toàn hơn để sử dụng rebase không là không phản ánh các thay đổi của bạn trên nhánh remote và thay vào đó thực hiện các thao tác sau:\n\n```sh\n(main)$ git checkout my-branch\n(my-branch)$ git rebase -i main\n(my-branch)$ git checkout main\n(main)$ git merge --ff-only my-branch\n```\n\nĐể biết thêm hãy xem [chủ đề này trên SO](https://stackoverflow.com/questions/11058312/how-can-i-use-git-rebase-without-requiring-a-forced-push).\n\n<a name=\"interactive-rebase\"></a>\n### Tôi cần kết hợp các commit\n\nGiả sử bạn đang làm việc trong một nhánh có / sẽ trở thành một pull-request cho `main`. Trong trường hợp đơn giản nhất khi bạn chỉ muốn là kết hợp *tất cả* các commit thành một commit và bạn không quan tâm đến timestamp (mốc thời gian) của commit, bạn có thể reset và commit lại. Đảm bảo rằng nhánh main được cập nhật và tất cả các thay đổi của bạn được commit, sau đó:\n\n```sh\n(my-branch)$ git reset --soft main\n(my-branch)$ git commit -am \"New awesome feature\"\n```\n\nNếu bạn muốn kiểm soát được nhiều hơn và cũng để bảo vệ timestamp, bạn cần phải làm một vài thứ được gọi là interactive rebase:\n\n```sh\n(my-branch)$ git rebase -i main\n```\n\nNếu bạn không làm việc với một nhánh khác, bạn phải rebase tương đối so với `HEAD` của bạn. Nếu bạn muốn gộp 2 commit cuối, bạn sẽ phải rebase tới `HEAD~2`. Cho 3 commit cuối, `HEAD~3`,...\n\n```sh\n(main)$ git rebase -i HEAD~2\n```\n\nSau khi bạn chạy lệnh interactive rebase, bạn sẽ thấy trông giống thế này trong trình soạn thảo (text editor) của bạn:\n\n```vim\npick a9c8a1d Some refactoring\npick 01b2fd8 New awesome feature\npick b729ad5 fixup\npick e3851e8 another fix\n\n# Rebase 8074d12..b729ad5 onto 8074d12\n#\n# Commands:\n#  p, pick = use commit\n#  r, reword = use commit, but edit the commit message\n#  e, edit = use commit, but stop for amending\n#  s, squash = use commit, but meld into previous commit\n#  f, fixup = like \"squash\", but discard this commit's log message\n#  x, exec = run command (the rest of the line) using shell\n#\n# These lines can be re-ordered; they are executed from top to bottom.\n#\n# If you remove a line here THAT COMMIT WILL BE LOST.\n#\n# However, if you remove everything, the rebase will be aborted.\n#\n# Note that empty commits are commented out\n```\n\nTất cả các dòng bắt đầu bằng một `#` là các comment (chú thích), chúng sẽ không ảnh hưởng đến rebase của bạn.\n\nSau đó bạn thay thể  lệnh `pick` với những bất cứ lệnh nào trong danh sách trên và bạn cũng có thể loại bỏ các commit khỏi rebase bằng cách xoá các dòng tương ứng.\n\nVí dụ, nếu bạn muốnn **dữ nguyên commit cũ nhất(đầu tiên) và kết hợp tất cả commit sau với commit cũ thứ hai**, bạn nên chỉnh sửa chữ cái bên cạnh mỗi commit ngoại trừ chữ cái đầu tiên và chữ cái thứ hai với `f`:\n\n```vim\npick a9c8a1d Some refactoring\npick 01b2fd8 New awesome feature\nf b729ad5 fixup\nf e3851e8 another fix\n```\n\nNếu bạn muốn kết hợp tất cả các commit **và đổi tên commit**, bạn nên thêm một chữ cái `r` bên cạnh commit thứ 2 hoặc đơn giản sử dụng `s` thay vì `f`:\n\n```vim\npick a9c8a1d Some refactoring\npick 01b2fd8 New awesome feature\ns b729ad5 fixup\ns e3851e8 another fix\n```\n\nBạn có thể đổi tên commit trong đoạn hội thoại sẽ bật lên.\n\n```vim\nNewer, awesomer features\n\n# Please enter the commit message for your changes. Lines starting\n# with '#' will be ignored, and an empty message aborts the commit.\n# rebase in progress; onto 8074d12\n# You are currently editing a commit while rebasing branch 'main' on '8074d12'.\n#\n# Changes to be committed:\n#   modified:   README.md\n#\n\n```\n\nNếu mọi thứ thành công, bạn sẽ thấy giống như thế này:\n\n```sh\n(main)$ Successfully rebased and updated refs/heads/main.\n```\n\n#### Chiến lược merge an toàn\n`--no-commit` thực hiện merge nhưng giả vờ kết hợp không thành công và không tự động tạo commit, cho phép người dùng có cơ hội kiểm tra và chỉnh thêm kết quả merge trước khi commit. `no-ff` duy trì bằng chứng rằng một nhánh tính năng đã từng tồn tại, giữ lịch sử dự án nhất quán.\n\n```sh\n(main)$ git merge --no-ff --no-commit my-branch\n```\n\n#### Tôi cần merge một nhánh thành một commit duy nhất\n\n```sh\n(main)$ git merge --squash my-branch\n```\n\n<a name=\"rebase-unpushed-commits\"></a>\n#### Tôi chỉ muốn kết hợp các commit chưa push\n\nĐôi khi bạn có một số commit trong khi công-việc-đang-tiến-hành và bạn muốn kết hợp thành một trước khi bạn đẩy lên upstream. Bạn không muốn vô tình kết hợp bất kỳ commit nào đã được push lên upstream vì người khác có thể đã thực hiện các commit tham chiếu chúng.\n\n```sh\n(main)$ git rebase -i @{u}\n```\n\nLệnh này sẽ thực hành một interactive rebase mà chỉ liệt kê các commit bạn chưa push, vì vậy mọi thứ sẽ an toàn để sắp xếp lại / sửa chữa / squash (gộp) bất cứ gì trong danh sách\n\n#### Tôi cần huỷ bỏ merge\n\nĐôi khi việc merge có thể gây ra sự cố trong một số file nhất định, trong những trường hợp đó, chúng ta có thể sử dụng cờ `abort` để hủy bỏ quá trình giải quyết xung đột hiện tại và cố gắng xây dựng lại trạng thái trước merge.\n\n```sh\n(my-branch)$ git merge --abort\n```\n\nLệnh này có sẵn từ phiên bản Git >= 1.7.4\n\n### Tôi cần cập nhật commit gốc (parent commit) cho nhánh của tôi\n\nGiả sử tôi có một nhánh main, một nhánh feature-1 tách từ main và một nhánh feature-2 tách từ feature-1. Nếu tôi thực hiện commit đối với feature-1, thì commit của feature-2 không còn chính xác nữa (gốc nên là đầu của feature-1, vì chúng ta đã tách nhánh từ nó). Chúng ta có thể sửa vấn đề này với `git rebase --onto`.\n\n```sh\n(feature-2)$ git rebase --onto feature-1 <commit đầu tiên trong nhánh feature-2 mà bạn không muốn mang theo> feature-2\n```\n\nLệnh này giúp trong các trường hợp khó nơi bạn có thể có một feature được xây dựng trên một feature khác chưa được merge, hoặc một bugfix (vá lỗi) trên nhánh feature-1 cần được phản ánh trong nhánh feature-2 của bạn.\n\n### Kiểm tra xem tất cả commit trên một nhánh đã được merge\n\nĐể kiểm tra tất cả commit trên một nhánh đã được merge vào nhánh khác, bạn nên diff (khác biệt) giữa các head (hoặc các commit) của các nhánh:\n\n```sh\n(main)$ git log --graph --left-right --cherry-pick --oneline HEAD...feature/120-on-scroll\n```\n\nLệnh này sẽ cho bạn biết nếu bất kỳ commit ở trong một nhánh nhưng không trong nhánh kia, và sẽ cung cấp cho bạn một danh sách của bất kỳ tệp không chia sẽ giữa các nhánh. Một lựa chọn khác là chạy lệnh:\n\n```sh\n(main)$ git log main ^feature/120-on-scroll --no-merges\n```\n\n### Các vấn đề có thể xảy ra với interactive rebase\n\n<a name=\"noop\"></a>\n#### Màn hình chỉnh sửa rebase ghi 'noop'\n\nNếu bạn thấy như sau:\n```\nnoop\n```\n\nĐiều này có nghĩa bạn đang cố rebase lại một nhánh đang có commit giống hệt hoặc là *ở trước* nhánh hiện tại. Bạn có thể thử:\n\n* đảm bảo nhánh main của bạn ở đúng chỗ\n* rebase với `HEAD~2` hoặc cũ hơn\n\n<a name=\"merge-conflict\"></a>\n#### Có một vài xung đột\n\nNếu bạn không thể hoàn tất thành công rebase, bạn có thể phải giải quyết xung đột.\n\nĐầu tiên chạy `git status` để xem tệp nào có xung đột:\n\n```sh\n(my-branch)$ git status\nOn branch my-branch\nChanges not staged for commit:\n  (use \"git add <file>...\" to update what will be committed)\n  (use \"git checkout -- <file>...\" to discard changes in working directory)\n\n  both modified:   README.md\n```\n\nTrong ví dụ đó, `README.md` có xung đột. Mở tệp đó và tìm những dòng trông như sau:\n\n```vim\n   <<<<<<< HEAD\n   some code\n   =========\n   some code\n   >>>>>>> new-commit\n```\n\nBạn sẽ cần phải giải quyết sự khác biệt giữa code đã được thêm vào với commit mới của bạn (trong ví dụ, mọi thứ từ dòng ở giữa cho đến  `new-commit`) và `HEAD` của bạn.\n\nNếu bạn muốn giữ phiên bản code của một nhánh, bạn có thể sử dụng `--ours` hoặc `--theirs`:\n\n```sh\n(main*)$ git checkout --ours README.md\n```\n\n- Khi *đang merge*, sử dụng `--ours` để giữ các thay đổi từ nhánh local, hoặc `--theirs` để giữ các thay đổi từ nhánh khác.\n- Khi *đang rebase*, sử dụng `--theirs` để giữ các thay đổi từ nhánh local, hoặc `--ours` để giữ các thay đổi từ nhánh khác. Để hiểu giải thích về sự hoán đổi này, hãy xem [ghi chú này trong tài liệu Git](https://git-scm.com/docs/git-rebase#Documentation/git-rebase.txt---merge).\n\nNếu việc merge phức tạp hơn, bạn có thể sử dụng trình chỉnh sửa khác biệt trực quan (visual diff editor):\n\n```sh\n(main*)$ git mergetool -t opendiff\n```\n\nSau khi bạn đã giải quyết tất cả xung đột và đã kiểm tra code của mình, `git add` các file đã thay đổi và sau đó tiếp tục rebase với `git rebase --continue`\n\n```sh\n(my-branch)$ git add README.md\n(my-branch)$ git rebase --continue\n```\n\nNếu sau khi giải quyết tất cả các xung đột bạn kết thúc với một cây giống hệt với cái trước khi thực hiện, bạn cần `git rebase --skip`.\n\nNếu bất kỳ lúc nào bạn muốn dừng toàn bộ quá trình rebase và quay trở lại trạng thái ban đầu nhánh của bạn, bạn có thể làm như thế này:\n\n```sh\n(my-branch)$ git rebase --abort\n```\n\n<a name=\"stashing\"></a>\n## Stash (Cất)\n\n### Stash tất cả chỉnh sửa\n\nĐể stash tất cả các chỉnh sửa trong thư mục làm việc\n\n```sh\n$ git stash\n```\n\nNếu bạn cũng muốn stash các file chưa được theo dõi, sử dụng cờ `-u`.\n\n```sh\n$ git stash -u\n```\n\n### Stash các file cụ thể\n\nĐể stash chỉ một file từ thư mục làm việc\n\n```sh\n$ git stash push working-directory-path/filename.ext\n```\n\nĐể stash nhiều file từ thư mục làm việc\n\n```sh\n$ git stash push working-directory-path/filename1.ext working-directory-path/filename2.ext\n```\n\n<a name=\"stash-msg\"></a>\n### Stash với message (thông điệp)\n\n```sh\n$ git stash save <message>\n```\n\nhoặc\n\n```sh\n$ git stash push -m <message>\n```\n\n<a name=\"stash-apply-specific\"></a>\n### Apply một stash cụ thể từ danh sách\n\nĐầu tiên kiểm tra danh sách các stash với message bằng lệnh\n\n```sh\n$ git stash list\n```\n\nSau đó apply (áp dụng) một stash cụ thể từ danh sách với\n\n```sh\n$ git stash apply \"stash@{n}\"\n```\n\nỞ đây, 'n' cho biết vị trí của stash trong stack. Stash trên cùng sẽ là vị trí 0.\n\nHơn nữa, cũng có thể chỉ stash dựa vào mốc thời gian\n\n```sh\n$ git stash apply \"stash@{2.hours.ago}\"\n```\n\n<a name=\"stage-and-keep-unstaged\"></a>\n### Stash trong khi giữ các thay đổi chưa stage\n\nBạn có thể  tạo một `stash commit`, rồi dùng lệnh  `git stash store`.\n\n```sh\n$ git stash create\n$ git stash store -m <message> CREATED_SHA1\n```\n\n## Finding (Tìm)\n\n### Tôi muốn tìm một chuỗi ký tự trong bất kỳ commit nào\n\nĐể tìm một chuỗi ký tự được giới thiệu với commit, bạn có thể sử dụng lệnh như sau:\n\n```sh\n$ git log -S \"chuỗi ký tự để tìm\"\n```\n\nCác cờ thường dùng:\n\n* `--source` có nghĩa là hiển thị tên ref được đưa ra trên dòng lệnh mà mỗi lần commit đã đạt tới.\n\n* `--all` nghĩa là bắt đầu từ mọi nhánh.\n\n* `--reverse` in theo thứ tự ngược lại, có nghĩa là hiển thị commit đầu tiên đã thực hiện thay đổi.\n\n<a name=\"find-by-committer\"></a>\n### Tôi muốn tìm tác giả hoặc người commit\n\nĐể tìm tất cả commit từ tác giả hoặc người commit bạn có thể sử dụng:\n\n```sh\n$ git log --author=<tên hoặc email>\n$ git log --committer=<tên hoặc email>\n```\n\nHãy nhớ rằng tác giả và người commit không giống nhau. `--author` là người ban đầu viết code; mặt khác,  `--committer`, là người đã commit code thay mặt tác giả gốc.\n\n### Tôi muốn liệt kê các commit chứa các file cụ thể\n\nĐể tìm tất cả các commit chưa một file cụ thể bạn có thể sử dụng:\n\n```sh\n$ git log -- <path to file>\n```\n\nBạn thường sẽ chỉ định một đường dẫn (filepath) chính xác, nhưng bạn cũng có thể sử dụng các ký tự đại diện bất kỳ cho đường dẫn và tên tệp:\n\n```sh\n$ git log -- **/*.js\n```\n\nTrong khi sử dụng ký tự đại diện bất kỳ, sẽ hữu ích hơn khi thêm `--name-status` để xem danh sách các tệp trong commit:\n\n```sh\n$ git log --name-status -- **/*.js\n```\n\n<a name=\"view-commit-history-for-specific-function\"></a>\n### Tôi muốn xem lịch sử commit của một function (chức năng) cụ thể\n\nĐể truy tìm lịch sử tiến hóa của một function là dùng lệnh:\n\n```sh\n$ git log -L :TênFunction:FilePath\n```\n\nGhi chú là bạn có thể xây dựng lệnh trên thêm với các cờ `git log` khác, giống như [phạm vi sửa đổi](https://git-scm.com/docs/gitrevisions) và [hạn mức commit](https://git-scm.com/docs/git-log/#_commit_limiting).\n\n### Tìm một tag mà một commit đã tham chiếu\n\nĐể tìm tất cả các tag có chứa một commit cụ thể\n\n```sh\n$ git tag --contains <commitid>\n```\n\n## Submodules\n\n<a name=\"clone-submodules\"></a>\n### Clone tất cả submodules\n\n```sh\n$ git clone --recursive git://github.com/foo/bar.git\n```\n\nNếu đã clone:\n\n```sh\n$ git submodule update --init --recursive\n```\n\n<a name=\"delete-submodule\"></a>\n### Xoá một submodule\n\nTạo một submodule là khá rõ rành, nhưng xóa chúng ít không như vậy. Các lệnh bạn cần là:\n\n```sh\n$ git submodule deinit submodulename\n$ git rm submodulename\n$ git rm --cached submodulename\n$ rm -rf .git/modules/submodulename\n```\n\n## Miscellaneous Objects (Những thứ khác)\n\n### Copy thư mục hoặc tệp file từ một nhánh sang nhánh khác\n\n```sh\n$ git checkout <nhánh-có-tệp-bạn-muốn> -- <thư mục hoặc tên file>\n```\n\n### Khôi phục một file đã bị xoá\n\nĐầu tiên tìm commit cuối cùng ma file vẫn tồn tại:\n\n```sh\n$ git rev-list -n 1 HEAD -- filename\n```\n\nSau đó checkout file:\n\n```\ngit checkout id-của-commit-delete-trên^ -- filename\n```\n\n### Xoá tag\n\n```sh\n$ git tag -d <tag_name>\n$ git push <remote> :refs/tags/<tag_name>\n```\n\n<a name=\"recover-tag\"></a>\n### Khôi phục một tag đã bị xoá\n\nNếu bạn muốn khôi phục tag đã bị xóa, bạn có thể làm được vậy với các bước sau: Trước tiên, bạn cần phải tìm tag không thể truy cập\n\n```sh\n$ git fsck --unreachable | grep tag\n```\n\nGhi lại mã hash của tag. Sau đó, khôi phục tag đã xóa theo cách sử  dụng [`git update-ref`](https://git-scm.com/docs/git-update-ref):\n\n```sh\n$ git update-ref refs/tags/<tag_name> <hash>\n```\n\nTag của bạn bây giờ đã được khôi phục.\n\n### Patch (Vá) bị xóa\n\nNếu ai đó đã gửi cho bạn một pull request trên GitHub, nhưng sau đó đã xoá chúng trên fork gốc, bạn sẽ không thể clone repository của họ hoặc sử dụng `git am` vì url của [.diff, .patch](https://github.com/blog/967-github-secrets) không dùng được. Nhưng bạn có thể checkout chính PR bằng cách sử dụng [GitHub's special refs](https://gist.github.com/piscisaureus/3342247). Để fetch nội dung của PR#1 vào một nhánh được gọi là pr_1, chạy:\n\n```sh\n$ git fetch origin refs/pull/1/head:pr_1\nFrom github.com:foo/bar\n * [new ref]         refs/pull/1/head -> pr_1\n```\n\n### Xuất một repository ra một file Zip\n\n```sh\n$ git archive --format zip --output /full/path/to/zipfile.zip main\n```\n### Push một nhánh và một tag có tên giống nhau\n\nNếu có một tag trên một remote repository mà có tên giống với một nhánh bạn sẽ gặp phải lỗi khi cố push nhanh với một lệnh `$ git push <remote> <branch>` bình thường.\n\n```sh\n$ git push origin <branch>\nerror: dst refspec same matches more than one.\nerror: failed to push some refs to '<git server>'\n```\n\nSửa lỗi này bằng cách chỉ định bạn muốn đẩy tham chiếu của head.\n\n```sh\n$ git push origin refs/heads/<branch-name>\n```\n\nNếu bạn muốn đẩy một tag vào một repository tại remote có cùng tên với một nhánh, bạn có thể sử dụng một lệnh tương tự.\n\n```sh\n$ git push origin refs/tags/<tag-name>\n```\n\n## Tracking (Theo dõi) các file\n\n<a name=\"change-file-name-capitalization-without-changing-contents\"></a>\n### Tôi muốn thay đổi cách viết hoa của tên tệp mà không thay đổi nội dung của tệp\n\n```sh\n(main)$ git mv --force myfile MyFile\n```\n\n### Tôi muốn ghi đè lên các tệp local khi thực hiện lệnh git pull\n\n```sh\n(main)$ git fetch --all\n(main)$ git reset --hard origin/main\n```\n\n<a name=\"remove-from-git\"></a>\n### Tôi muốn xóa một tệp khỏi Git nhưng vẫn giữ tệp\n\n```sh\n(main)$ git rm --cached log.txt\n```\n\n### Tôi muốn đảo ngược tệp về bản sửa đổi cụ thể\n\nGiả sử mã hash của commit bạn muốn là c5f567:\n\n```sh\n(main)$ git checkout c5f567 -- fileSố1/Để/PhụcHồi fileSố2/Để/PhụcHồi\n```\n\nNếu bạn muốn đảo ngược các thay đổi được thực hiện chỉ 1 commit trước c5f567, đưa số hash commit như c5f567~1:\n\n```sh\n(main)$ git checkout c5f567~1 -- file1/to/restore file2/to/restore\n```\n\n### Tôi muốn liệt kê các thay đổi của một tệp cụ thể giữa các commit hoặc các nhánh\n\nGiả sử bạn muốn so sánh commit cuối cùng với tệp từ commit c5f567:\n\n```sh\n$ git diff HEAD:path_to_file/file c5f567:path_to_file/file\n# hoặc\n$ git diff HEAD c5f567 -- path_to_file/file\n```\n\nCũng giống khi so sánh nhánh nhánh:\n\n```sh\n$ git diff main:path_to_file/file staging:path_to_file/file\n# hoặc\n$ git diff main staging -- path_to_file/file\n```\n\n### Tôi muốn Git bỏ qua những thay đổi đối với một tệp cụ thể\n\nCác bước sau khá hợp cho các mẫu cấu hình hoặc các tệp yêu cầu thêm thông tin đăng nhập tại local mà không nên commit\n\n```sh\n$ git update-index --assume-unchanged file-to-ignore\n```\n\nLưu ý rằng điều này không xóa tệp khỏi kiểm soát source - nó chỉ bị bỏ qua tại local. Để hoán đổi thao tác này và yêu cầu Git lại chú ý các thay đổi, lệnh sau sẽ xóa cờ bỏ qua (ignore flag):\n\n```sh\n$ git update-index --no-assume-unchanged file-to-stop-ignoring\n```\n\n## Debugging (Gỡ lỗi) with Git\n\nLệnh [git-bisect](https://git-scm.com/docs/git-bisect) sử dụng tìm nhị phân để tìm commit đã giớ thiệu lỗi.\n\nGiả sử bạn đang ở nhánh `main` và bạn muốn tìm commit đã làm hỏng cái gì đó. Bạn bắt đầu bisect với: \n\n```sh\n$ git bisect start\n```\n\nSau đó bạn đề rõ commit nào tồi và commit nào biết là tốt. Giả sử bạn biết phiên bản *hiện tại* là tồi, và `v1.1.1` là tốt: \n\n```sh\n$ git bisect bad\n$ git bisect good v1.1.1\n```\n\nBây giờ `git-bisect` chọn commit ở giữa khoảng cách bạn lựa chọn, checkout cái commit đấy, và hỏi bạn là commit này tồi hay tốt. Bạn sẽ thấy giống như thế này:\n\n```sh\n$ Bisecting: 5 revision left to test after this (roughly 5 step)\n$ [c44abbbee29cb93d8499283101fe7c8d9d97f0fe] Commit message\n$ (c44abbb)$\n```\n\nBạn kiểm tra commit xem tốt hay tồi. Nếu tốt:\n\n```sh\n$ (c44abbb)$ git bisect good\n```\n\nvà `git-bisect` sẽ chọn một commit khác trong phạm vi của bạn. Quá trình này sẽ tiếp tục lặp lại cho đến khi không còn sửa đổi cần kiểm tra, và lệnh sẽ cuối cùng in ra mô tả của commit tồi **đầu tiên**\n\n## Cấu hình (Configuration)\n\n### Tôi muốn thêm bí danh (alias) cho một số lệnh Git\n\nTrên OS X và Linux, file cấu hình git được lưu trong ```~/.gitconfig```.  Tôi đã thêm một số bí danh mẫu mà tôi sử dụng làm shortcut (và một số lỗi chính tả phổ biến của tôi) trong phần ```[alias]``` được hiển thị như dưới đây:\n\n```vim\n[alias]\n    a = add\n    amend = commit --amend\n    c = commit\n    ca = commit --amend\n    ci = commit -a\n    co = checkout\n    d = diff\n    dc = diff --changed\n    ds = diff --staged\n    extend = commit --amend -C HEAD\n    f = fetch\n    loll = log --graph --decorate --pretty=oneline --abbrev-commit\n    m = merge\n    one = log --pretty=oneline\n    outstanding = rebase -i @{u}\n    reword = commit --amend --only\n    s = status\n    unpushed = log @{u}\n    wc = whatchanged\n    wip = rebase -i @{u}\n    zap = fetch -p\n        day = log --reverse --no-merges --branches=* --date=local --since=midnight --author=\\\"$(git config --get user.name)\\\"\n    delete-merged-branches = \"!f() { git checkout --quiet main && git branch --merged | grep --invert-match '\\\\*' | xargs -n 1 git branch --delete; git checkout --quiet @{-1}; }; f\"\n```\n\n### Tôi muốn thêm một thư mục trống vào repository của tôi\n\nBạn không thể! Git không hỗ trợ điều này, nhưng có một hack. Bạn có thể tạo tệp .gitignore trong thư mục với các nội dung sau:\n\n```\n # Bỏ qua tất cả mọi thứ trong repository\n *\n # Ngoại trừ file này\n !.gitignore\n```\n\nMột quy ước chung khác là tạo một tệp trống trong thư mục có tên .gitkeep.\n\n```sh\n$ mkdir mydir\n$ touch mydir/.gitkeep\n```\n\nBạn cũng có thể đặt tên tệp là .keep, trong trường hợp đó dòng thứ hai ở trên sẽ ```touch mydir/.keep```\n\n### Tôi muốn cache (cho vào bộ nhớ đệm) một username và password cho một repository\n\nBạn có thể có một repository yêu cầu xác thực (authentication).  Trong trường hợp này bạn có thể cache một username và password vì vậy bạn không phải nhập nó vào mỗi lần push / pull. Phụ tá chứng chỉ(credential.helper) có thể làm điều này cho bạn.\n\n```sh\n$ git config --global credential.helper cache\n# Đặt git dùng bộ nhớ đệm chứng chỉ\n```\n\n```sh\n$ git config --global credential.helper 'cache --timeout=3600'\n# Đặt bộ nhớ đệm kết thúc sau 1h (cấu hình dùng giây/s)\n```\n\nĐể tìm phụ tá chứng chỉ:\n\n```sh\n$ git help -a | grep credential\n# Phô bày các phụ tá chứng chỉ\n```\n\nBộ nhớ đệm chứng chỉ cho các hệ điều hành (operating system/OS) cụ thể :\n\n```sh\n$ git config --global credential.helper osxkeychain\n# cho OSX\n```\n\n```sh\n$ git config --global credential.helper manager\n# Git for Windows 2.7.3+\n```\n\n```sh\n$ git config --global credential.helper gnome-keyring\n# Ubuntu và các bản phân phối dựa trên GNOME\n```\n\nCác phụ tá chứng chỉ khác có khả năng cao tìm được cho các bản phân phối và hệ điều hành khác.\n\n### Tôi muốn Git bỏ qua các quyền và thay đổi về filemode (chế độ file)\n\n```sh\n$ git config core.fileMode false\n```\n\nNếu bạn muốn đặt hành vi này là hành vi mặc định cho người dùng đã đăng nhập, thì hãy sử dụng:\n\n```sh\n$ git config --global core.fileMode false\n```\n\n### Tôi muốn đặt người dùng toàn cục (global user)\n\nĐể cấu hình thông tin người dùng được sử dụng trên tất cả các repository tại local và để đặt tên có thể nhận dạng khi xem lịch sử phiên bản:\n\n```sh\n$ git config --global user.name \"[tên-riêng tên-họ]\"\n```\n\nĐể đặt địa chỉ email gắn với mỗi mốc lịch sử:\n\n```sh\ngit config --global user.email \"[email-có-hiệu-lực]\"\n```\n\n## Tôi không biết mình đã làm gì sai\n\nOk, bạn gặp rắc rối lớn - bạn `reset` vài thứ, hoặc bạn merge sai nhánh, hoặc bạn push ép (force push) và bây giờ bạn không thể tìm thấy các commit của bạn. Bạn biết, tại một số thời điểm, bạn không có vấn đề và bạn muốn quay trở lại trạng thái bạn đang ở đó.\n\nĐây là tình huống cho `git reflog`. `reflog` theo dõi bất kỳ thay đổi nào đối với đầu nhánh, ngay cả khi đầu nhánh đó không được tham chiếu bởi nhánh hoặc tag. Về cơ bản, mỗi lần HEAD thay đổi, một mục mới được thêm vào reflog. Thật đáng buồn là cách này chỉ hoạt động tốt đối với các repository ở local, và nó chỉ theo dõi các chuyển động (ví dụ: không thay đổi một tệp không được ghi ở bất kỳ đâu).\n\n```sh\n(main)$ git reflog\n0a2e358 HEAD@{0}: reset: moving to HEAD~2\n0254ea7 HEAD@{1}: checkout: moving from 2.2 to main\nc10f740 HEAD@{2}: checkout: moving from main to 2.2\n```\n\nCác reflog ở trên cho thấy một checkout từ main đến nhánh 2.2 rồi quay trở lại. Từ đó, có một reset cứng về một commit cũ hơn. Hoạt động mới nhất được thể hiện ở đầu được gắn nhãn `HEAD@{0}`.\n\nNếu nó chỉ ra rằng bạn vô tình di chuyển trở lại, các reflog sẽ chứa commit mà main chỉ đến (0254ea7) trước khi bạn vô tình giảm 2 commit\n\n```sh\n$ git reset --hard 0254ea7\n```\n\nSử dụng `git reset` để có thể thay đổi main trở về commit trước đó. Cách này cung cấp mạng lưới an toàn trong trường hợp lịch sử vô tình bị thay đổi.\n\n(đã sao chép và chỉnh sửa từ [Source](https://www.atlassian.com/git/tutorials/rewriting-history/git-reflog)).\n\n<a name=\"git-shortcuts\"></a>\n## Git Shortcuts (phím tắt)\n\n### Git Bash\n\nMột khi bạn thấy thoải mái với các lệnh trên, bạn có thể muốn tạo các phím tắt cho Git Bash. Cách này giúp bạn làm việc nhanh hơn vì chạy các hành vi phức tạp với các lệnh ngắn hơn.\n\n```sh\nalias sq=squash\n\nfunction squash() {\n    git rebase -i HEAD~$1\n}\n```\n\nCopy các lệnh này vào .bashrc hoặc .bash_profile của bạn.\n\n### PowerShell trên Windows\n\nNếu bạn dùng Powershell trên Windows, bạn cũng có thể đặt các bí danh và chức năng tắt. Cho thêm các lệnh này vào prolfe của bạn, đường dẫn được định nghĩa ở biến `$profile`. Học thêm với trang [About Profiles](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_profiles) tại trang tài liệu tham khảo của Microsoft .\n\n```powershell\nSet-Alias sq Squash-Commits\n\nfunction Squash-Commits {\n  git rebase -i HEAD~$1\n}\n```\n\n# Tài nguyên khác\n\n## Sách\n\n* [Learn Enough Git to Be Dangerous](https://www.learnenough.com/git-tutorial) - Sách của Michael Hartl cho Git từ những điều cơ bản\n* [Pro Git](https://git-scm.com/book/en/v2) - Một cuốn sách xuất chúng của Scott Chacon và Ben Straub\n* [Git Internals](https://github.com/pluralsight/git-internals-pdf) - Cuốn sách xuất chúng khác về Git của Scott Chacon\n* [Sổ tay NASA](https://www.nasa.gov/sites/default/files/atoms/files/nasa_systems_engineering_handbook.pdf)\n\n## Hướng dẫn\n\n* [19 mẹo sử dụng GIT hàng ngày](https://www.alexkras.com/19-git-tips-for-everyday-use) - Một danh sách các mẹo dùng GIT hữu ích.\n* [Hướng dẫn Git của Atlassian](https://www.atlassian.com/git/tutorials) - Sử dụng Git đúng với các hướng dẫn từ cơ bản đến nâng cao.\n* [Học về nhánh Git](https://learngitbranching.js.org/) - Hướng dẫn phân nhánh / merging / rebasing dựa trên web interactive\n* [Chở nên vững chắc về Git rebase vs. merge](https://medium.com/@porteneuve/getting-solid-at-git-rebase-vs-merge-4fa1a48c53aa)\n* [Tờ gian lận lệnh và thực hành tốt Git ](https://zeroturnaround.com/rebellabs/git-commands-and-best-practices-cheat-sheet) - Một Git cheat sheet trong một bài đăng trên blog với nhiều giải thích hơn\n* [Git từ trong ra ngoài](https://codewords.recurse.com/issues/two/git-from-the-inside-out) - Hướng dẫn đi sâu vào Git\n* [git-workflow](https://github.com/asmeurer/git-workflow) - [Aaron Meurer](https://github.com/asmeurer) viết cách sử dụng Git để đóng góp vào repository mã nguồn mở (open source)\n* [GitHub as a workflow](https://hugogiraudel.com/2015/08/13/github-as-a-workflow/) - Một ý kiến thú vị về sử dụng GitHub như một quy trình làm việc, đặc biệt với các PR trống.\n* [Githug](https://github.com/Gazler/githug) - Một trò chơi để học thêm về luồng làm việc thường thấy của Git.\n* [learnGitBranching](https://github.com/pcottle/learnGitBranching) - Hình dung git có tương tác để thử thách và giáo dục!\n\n## Scripts (tập lệnh) và các công cụ\n\n* [firstaidgit.io](http://firstaidgit.io/) - Danh sách được lựa chọn có thể tìm kiếm các câu hỏi thường gặp về Git\n* [git-extra-commands](https://github.com/unixorn/git-extra-commands) - Tập hợp các script Git mở rộng hữu ích\n* [git-extras](https://github.com/tj/git-extras) - Các tiện ích GIT -- Repo tóm tắt, thay thế, số lượng thay đổi, tỷ lệ phần trăm của tác giả và nhiều nữa\n* [git-fire](https://github.com/qw3rtman/git-fire) - git-fire là một plugin cho Git để giúp trong trường hợp khẩn cấp bằng cách thêm tất cả các tệp hiện tại, commit và push vào một nhánh mới (để ngăn xung đột khi merge).\n* [git-tips](https://github.com/git-tips/tips) - Các mẹo Git nhỏ\n* [git-town](https://github.com/Originate/git-town) - Hỗ trợ luồng làm việc Git chung, tầm nâng cao! http://www.git-town.com\n\n## GUI Clients\n\n* [GitKraken](https://www.gitkraken.com/) - Client sang trọng cho Windows, Mac & Linux\n* [git-cola](https://git-cola.github.io/) - Git client khác cho Windows và OS X\n* [GitUp](https://github.com/git-up/GitUp) - Một GUI mới mẻ mà có một số cách rất quan tâm để giải quyết các việc khó chịu của Git\n* [gitx-dev](https://rowanj.github.io/gitx/) - Một Git client đồ hoạ khác cho OS X\n* [Sourcetree](https://www.sourcetreeapp.com/) - Sự đơn giản nhưng mạnh mẽ cho giao diện Git đẹp và miễn phí cho Windows và Mac.\n* [Tower](https://www.git-tower.com/) - Git client đồ hoạ cho OS X (trả phí)\n* [tig](https://jonas.github.io/tig/) - Terminal text-mode interface cho Git\n* [Magit](https://magit.vc/) - Interface cho Git thực hiện như một gói Emacs .\n* [GitExtensions](https://github.com/gitextensions/gitextensions) - Một shell extension, một Visual Studio 2010-2015 plugin và một công cụ Git repository độc lập.\n* [Fork](https://git-fork.com/) - Một Git client nhanh và thân thiện cho Mac (beta)\n* [gmaster](https://gmaster.io/) - Một Git client cho Windows với 3 cách merge, analyze refactors, semantic diff và merge (beta)\n* [gitk](https://git-scm.com/docs/gitk) - Một Git client cho Linux để cho phép xem đơn giản cho trạng thái repo.\n* [SublimeMerge](https://www.sublimemerge.com/) - Client nhanh, mở rộng, cung cấp 3 cách merge, tìm kiếm mạnh mẽ và làm nổi bật cú pháp, đang phát triển tích cực.\n"
  },
  {
    "path": "README_zh-CN.md",
    "content": "# Git飞行规则(Flight Rules)\n\n🌍\n*[English](README.md) ∙ [Español](README_es.md)  ∙  [Русский](README_ru.md) ∙ [繁體中文](README_zh-TW.md) ∙ [简体中文](README_zh-CN.md) ∙ [한국어](README_kr.md)  ∙  [Tiếng Việt](README_vi.md) ∙ [Français](README_fr.md) ∙ [日本語](README_ja.md)*\n\n#### 前言\n\n- 英文原版[README](https://github.com/k88hudson/git-flight-rules/blob/master/README.md)\n- 翻译可能存在错误或不标准的地方，欢迎大家指正和修改，谢谢！\n\n#### 什么是\"飞行规则\"?\n\n这是一篇给宇航员（这里就是指使用Git的程序员们）的指南，用来指导问题出现后的应对之法。\n\n>  *飞行规则(Flight Rules)* 是记录在手册上的来之不易的一系列知识，记录了某个事情发生的原因，以及怎样一步一步的进行处理。本质上, 它们是特定场景的非常详细的标准处理流程。 [...]\n\n> 自20世纪60年代初以来，NASA一直在捕捉(capturing)我们的失误，灾难和解决方案, 当时水星时代(Mercury-era)的地面小组首先开始将“经验教训”收集到一个纲要(compendium)中，该纲现在已经有上千个问题情景，从发动机故障到破损的舱口把手到计算机故障，以及它们对应的解决方案。\n\n&mdash; Chris Hadfield, *一个宇航员的生活指南(An Astronaut's Guide to Life)*。\n\n#### 这篇文章的约定\n\n为了清楚的表述，这篇文档里的所有例子使用了自定义的bash 提示，以便指示当前分支和是否有暂存的变化(changes)。分支名用小括号括起来，分支名后面跟的`*`表示暂存的变化(changes)。\n\n[![Join the chat at https://gitter.im/k88hudson/git-flight-rules](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/k88hudson/git-flight-rules?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n  - [编辑提交(editting commits)](#%E7%BC%96%E8%BE%91%E6%8F%90%E4%BA%A4editting-commits)\n    - [我刚才提交了什么?](#%E6%88%91%E5%88%9A%E6%89%8D%E6%8F%90%E4%BA%A4%E4%BA%86%E4%BB%80%E4%B9%88)\n    - [我的提交信息(commit message)写错了](#%E6%88%91%E7%9A%84%E6%8F%90%E4%BA%A4%E4%BF%A1%E6%81%AFcommit-message%E5%86%99%E9%94%99%E4%BA%86)\n    - [我提交(commit)里的用户名和邮箱不对](#%E6%88%91%E6%8F%90%E4%BA%A4commit%E9%87%8C%E7%9A%84%E7%94%A8%E6%88%B7%E5%90%8D%E5%92%8C%E9%82%AE%E7%AE%B1%E4%B8%8D%E5%AF%B9)\n    - [我想从一个提交(commit)里移除一个文件](#%E6%88%91%E6%83%B3%E4%BB%8E%E4%B8%80%E4%B8%AA%E6%8F%90%E4%BA%A4commit%E9%87%8C%E7%A7%BB%E9%99%A4%E4%B8%80%E4%B8%AA%E6%96%87%E4%BB%B6)\n    - [我想删除我的最后一次提交(commit)](#%E6%88%91%E6%83%B3%E5%88%A0%E9%99%A4%E6%88%91%E7%9A%84%E7%9A%84%E6%9C%80%E5%90%8E%E4%B8%80%E6%AC%A1%E6%8F%90%E4%BA%A4commit)\n    - [删除任意提交(commit)](#%E5%88%A0%E9%99%A4%E4%BB%BB%E6%84%8F%E6%8F%90%E4%BA%A4commit)\n    - [我尝试推一个修正后的提交(amended commit)到远程，但是报错：](#%E6%88%91%E5%B0%9D%E8%AF%95%E6%8E%A8%E4%B8%80%E4%B8%AA%E4%BF%AE%E6%AD%A3%E5%90%8E%E7%9A%84%E6%8F%90%E4%BA%A4amended-commit%E5%88%B0%E8%BF%9C%E7%A8%8B%E4%BD%86%E6%98%AF%E6%8A%A5%E9%94%99)\n    - [我意外的做了一次硬重置(hard reset)，我想找回我的内容](#%E6%88%91%E6%84%8F%E5%A4%96%E7%9A%84%E5%81%9A%E4%BA%86%E4%B8%80%E6%AC%A1%E7%A1%AC%E9%87%8D%E7%BD%AEhard-reset%E6%88%91%E6%83%B3%E6%89%BE%E5%9B%9E%E6%88%91%E7%9A%84%E5%86%85%E5%AE%B9)\n  - [暂存(Staging)](#%E6%9A%82%E5%AD%98staging)\n    - [我需要把暂存的内容添加到上一次的提交(commit)](#%E6%88%91%E9%9C%80%E8%A6%81%E6%8A%8A%E6%9A%82%E5%AD%98%E7%9A%84%E5%86%85%E5%AE%B9%E6%B7%BB%E5%8A%A0%E5%88%B0%E4%B8%8A%E4%B8%80%E6%AC%A1%E7%9A%84%E6%8F%90%E4%BA%A4commit)\n    - [我想要暂存一个新文件的一部分，而不是这个文件的全部](#%E6%88%91%E6%83%B3%E8%A6%81%E6%9A%82%E5%AD%98%E4%B8%80%E4%B8%AA%E6%96%B0%E6%96%87%E4%BB%B6%E7%9A%84%E4%B8%80%E9%83%A8%E5%88%86%E8%80%8C%E4%B8%8D%E6%98%AF%E8%BF%99%E4%B8%AA%E6%96%87%E4%BB%B6%E7%9A%84%E5%85%A8%E9%83%A8)\n    - [我想把在一个文件里的变化(changes)加到两个提交(commit)里](#%E6%88%91%E6%83%B3%E6%8A%8A%E5%9C%A8%E4%B8%80%E4%B8%AA%E6%96%87%E4%BB%B6%E9%87%8C%E7%9A%84%E5%8F%98%E5%8C%96changes%E5%8A%A0%E5%88%B0%E4%B8%A4%E4%B8%AA%E6%8F%90%E4%BA%A4commit%E9%87%8C)\n    - [我想把暂存的内容变成未暂存，把未暂存的内容暂存起来](#%E6%88%91%E6%83%B3%E6%8A%8A%E6%9A%82%E5%AD%98%E7%9A%84%E5%86%85%E5%AE%B9%E5%8F%98%E6%88%90%E6%9C%AA%E6%9A%82%E5%AD%98%E6%8A%8A%E6%9C%AA%E6%9A%82%E5%AD%98%E7%9A%84%E5%86%85%E5%AE%B9%E6%9A%82%E5%AD%98%E8%B5%B7%E6%9D%A5)\n  - [未暂存(Unstaged)的内容](#%E6%9C%AA%E6%9A%82%E5%AD%98unstaged%E7%9A%84%E5%86%85%E5%AE%B9)\n    - [我想把未暂存的内容移动到一个新分支](#%E6%88%91%E6%83%B3%E6%8A%8A%E6%9C%AA%E6%9A%82%E5%AD%98%E7%9A%84%E5%86%85%E5%AE%B9%E7%A7%BB%E5%8A%A8%E5%88%B0%E4%B8%80%E4%B8%AA%E6%96%B0%E5%88%86%E6%94%AF)\n    - [我想把未暂存的内容移动到另一个已存在的分支](#%E6%88%91%E6%83%B3%E6%8A%8A%E6%9C%AA%E6%9A%82%E5%AD%98%E7%9A%84%E5%86%85%E5%AE%B9%E7%A7%BB%E5%8A%A8%E5%88%B0%E5%8F%A6%E4%B8%80%E4%B8%AA%E5%B7%B2%E5%AD%98%E5%9C%A8%E7%9A%84%E5%88%86%E6%94%AF)\n    - [我想丢弃本地未提交的变化(uncommitted changes)](#%E6%88%91%E6%83%B3%E4%B8%A2%E5%BC%83%E6%9C%AC%E5%9C%B0%E6%9C%AA%E6%8F%90%E4%BA%A4%E7%9A%84%E5%8F%98%E5%8C%96uncommitted-changes)\n    - [我想丢弃某些未暂存的内容](#%E6%88%91%E6%83%B3%E4%B8%A2%E5%BC%83%E6%9F%90%E4%BA%9B%E6%9C%AA%E6%9A%82%E5%AD%98%E7%9A%84%E5%86%85%E5%AE%B9)\n  - [分支(Branches)](#%E5%88%86%E6%94%AFbranches)\n    - [我从错误的分支拉取了内容，或把内容拉取到了错误的分支](#%E6%88%91%E4%BB%8E%E9%94%99%E8%AF%AF%E7%9A%84%E5%88%86%E6%94%AF%E6%8B%89%E5%8F%96%E4%BA%86%E5%86%85%E5%AE%B9%E6%88%96%E6%8A%8A%E5%86%85%E5%AE%B9%E6%8B%89%E5%8F%96%E5%88%B0%E4%BA%86%E9%94%99%E8%AF%AF%E7%9A%84%E5%88%86%E6%94%AF)\n    - [我想扔掉本地的提交(commit)，以便我的分支与远程的保持一致](#%E6%88%91%E6%83%B3%E6%89%94%E6%8E%89%E6%9C%AC%E5%9C%B0%E7%9A%84%E6%8F%90%E4%BA%A4commit%E4%BB%A5%E4%BE%BF%E6%88%91%E7%9A%84%E5%88%86%E6%94%AF%E4%B8%8E%E8%BF%9C%E7%A8%8B%E7%9A%84%E4%BF%9D%E6%8C%81%E4%B8%80%E8%87%B4)\n    - [我需要提交到一个新分支，但错误的提交到了main](#%E6%88%91%E9%9C%80%E8%A6%81%E6%8F%90%E4%BA%A4%E5%88%B0%E4%B8%80%E4%B8%AA%E6%96%B0%E5%88%86%E6%94%AF%E4%BD%86%E9%94%99%E8%AF%AF%E7%9A%84%E6%8F%90%E4%BA%A4%E5%88%B0%E4%BA%86main)\n    - [我想保留来自另外一个ref-ish的整个文件](#%E6%88%91%E6%83%B3%E4%BF%9D%E7%95%99%E6%9D%A5%E8%87%AA%E5%8F%A6%E5%A4%96%E4%B8%80%E4%B8%AAref-ish%E7%9A%84%E6%95%B4%E4%B8%AA%E6%96%87%E4%BB%B6)\n    - [我把几个提交(commit)提交到了同一个分支，而这些提交应该分布在不同的分支里](#%E6%88%91%E6%8A%8A%E5%87%A0%E4%B8%AA%E6%8F%90%E4%BA%A4commit%E6%8F%90%E4%BA%A4%E5%88%B0%E4%BA%86%E5%90%8C%E4%B8%80%E4%B8%AA%E5%88%86%E6%94%AF%E8%80%8C%E8%BF%99%E4%BA%9B%E6%8F%90%E4%BA%A4%E5%BA%94%E8%AF%A5%E5%88%86%E5%B8%83%E5%9C%A8%E4%B8%8D%E5%90%8C%E7%9A%84%E5%88%86%E6%94%AF%E9%87%8C)\n    - [我想删除上游(upstream)分支被删除了的本地分支](#%E6%88%91%E6%83%B3%E5%88%A0%E9%99%A4%E4%B8%8A%E6%B8%B8upstream%E5%88%86%E6%94%AF%E8%A2%AB%E5%88%A0%E9%99%A4%E4%BA%86%E7%9A%84%E6%9C%AC%E5%9C%B0%E5%88%86%E6%94%AF)\n    - [我不小心删除了我的分支](#%E6%88%91%E4%B8%8D%E5%B0%8F%E5%BF%83%E5%88%A0%E9%99%A4%E4%BA%86%E6%88%91%E7%9A%84%E5%88%86%E6%94%AF)\n    - [我想删除一个分支](#%E6%88%91%E6%83%B3%E5%88%A0%E9%99%A4%E4%B8%80%E4%B8%AA%E5%88%86%E6%94%AF)\n    - [我想从别人正在工作的远程分支签出(checkout)一个分支](#%E6%88%91%E6%83%B3%E4%BB%8E%E5%88%AB%E4%BA%BA%E6%AD%A3%E5%9C%A8%E5%B7%A5%E4%BD%9C%E7%9A%84%E8%BF%9C%E7%A8%8B%E5%88%86%E6%94%AF%E7%AD%BE%E5%87%BAcheckout%E4%B8%80%E4%B8%AA%E5%88%86%E6%94%AF)\n  - [Rebasing 和合并(Merging)](#rebasing-%E5%92%8C%E5%90%88%E5%B9%B6merging)\n    - [我想撤销rebase/merge](#%E6%88%91%E6%83%B3%E6%92%A4%E9%94%80rebasemerge)\n    - [我已经rebase过, 但是我不想强推(force push)](#%E6%88%91%E5%B7%B2%E7%BB%8Frebase%E8%BF%87-%E4%BD%86%E6%98%AF%E6%88%91%E4%B8%8D%E6%83%B3%E5%BC%BA%E6%8E%A8force-push)\n    - [我需要组合(combine)几个提交(commit)](#%E6%88%91%E9%9C%80%E8%A6%81%E7%BB%84%E5%90%88combine%E5%87%A0%E4%B8%AA%E6%8F%90%E4%BA%A4commit)\n      - [安全合并(merging)策略](#%E5%AE%89%E5%85%A8%E5%90%88%E5%B9%B6merging%E7%AD%96%E7%95%A5)\n      - [我需要将一个分支合并成一个提交(commit)](#%E6%88%91%E9%9C%80%E8%A6%81%E5%B0%86%E4%B8%80%E4%B8%AA%E5%88%86%E6%94%AF%E5%90%88%E5%B9%B6%E6%88%90%E4%B8%80%E4%B8%AA%E6%8F%90%E4%BA%A4commit)\n      - [我只想组合(combine)未推的提交(unpushed commit)](#%E6%88%91%E5%8F%AA%E6%83%B3%E7%BB%84%E5%90%88combine%E6%9C%AA%E6%8E%A8%E7%9A%84%E6%8F%90%E4%BA%A4unpushed-commit)\n    - [检查是否分支上的所有提交(commit)都合并(merge)过了](#%E6%A3%80%E6%9F%A5%E6%98%AF%E5%90%A6%E5%88%86%E6%94%AF%E4%B8%8A%E7%9A%84%E6%89%80%E6%9C%89%E6%8F%90%E4%BA%A4commit%E9%83%BD%E5%90%88%E5%B9%B6merge%E8%BF%87%E4%BA%86)\n    - [交互式rebase(interactive rebase)可能出现的问题](#%E4%BA%A4%E4%BA%92%E5%BC%8Frebaseinteractive-rebase%E5%8F%AF%E8%83%BD%E5%87%BA%E7%8E%B0%E7%9A%84%E9%97%AE%E9%A2%98)\n      - [这个rebase 编辑屏幕出现'noop'](#%E8%BF%99%E4%B8%AArebase-%E7%BC%96%E8%BE%91%E5%B1%8F%E5%B9%95%E5%87%BA%E7%8E%B0noop)\n      - [有冲突的情况](#%E6%9C%89%E5%86%B2%E7%AA%81%E7%9A%84%E6%83%85%E5%86%B5)\n  - [Stash](#stash)\n    - [暂存所有改动](#%E6%9A%82%E5%AD%98%E6%89%80%E6%9C%89%E6%94%B9%E5%8A%A8)\n    - [暂存指定文件](#%E6%9A%82%E5%AD%98%E6%8C%87%E5%AE%9A%E6%96%87%E4%BB%B6)\n    - [暂存时记录消息](#%E6%9A%82%E5%AD%98%E6%97%B6%E8%AE%B0%E5%BD%95%E6%B6%88%E6%81%AF)\n    - [使用某个指定暂存](#%E4%BD%BF%E7%94%A8%E6%9F%90%E4%B8%AA%E6%8C%87%E5%AE%9A%E6%9A%82%E5%AD%98)\n    - [暂存时保留未暂存的内容](#%E6%9A%82%E5%AD%98%E6%97%B6%E4%BF%9D%E7%95%99%E6%9C%AA%E6%9A%82%E5%AD%98%E7%9A%84%E5%86%85%E5%AE%B9)\n  - [杂项(Miscellaneous Objects)](#%E6%9D%82%E9%A1%B9miscellaneous-objects)\n    - [克隆所有子模块](#%E5%85%8B%E9%9A%86%E6%89%80%E6%9C%89%E5%AD%90%E6%A8%A1%E5%9D%97)\n    - [删除标签(tag)](#%E5%88%A0%E9%99%A4%E6%A0%87%E7%AD%BEtag)\n    - [恢复已删除标签(tag)](#%E6%81%A2%E5%A4%8D%E5%B7%B2%E5%88%A0%E9%99%A4%E6%A0%87%E7%AD%BEtag)\n    - [已删除补丁(patch)](#%E5%B7%B2%E5%88%A0%E9%99%A4%E8%A1%A5%E4%B8%81patch)\n  - [跟踪文件(Tracking Files)](#%E8%B7%9F%E8%B8%AA%E6%96%87%E4%BB%B6tracking-files)\n    - [我只想改变一个文件名字的大小写，而不修改内容](#%E6%88%91%E5%8F%AA%E6%83%B3%E6%94%B9%E5%8F%98%E4%B8%80%E4%B8%AA%E6%96%87%E4%BB%B6%E5%90%8D%E5%AD%97%E7%9A%84%E5%A4%A7%E5%B0%8F%E5%86%99%E8%80%8C%E4%B8%8D%E4%BF%AE%E6%94%B9%E5%86%85%E5%AE%B9)\n    - [我想从Git删除一个文件，但保留该文件](#%E6%88%91%E6%83%B3%E4%BB%8Egit%E5%88%A0%E9%99%A4%E4%B8%80%E4%B8%AA%E6%96%87%E4%BB%B6%E4%BD%86%E4%BF%9D%E7%95%99%E8%AF%A5%E6%96%87%E4%BB%B6)\n  - [配置(Configuration)](#%E9%85%8D%E7%BD%AEconfiguration)\n    - [我想给一些Git命令添加别名(alias)](#%E6%88%91%E6%83%B3%E7%BB%99%E4%B8%80%E4%BA%9Bgit%E5%91%BD%E4%BB%A4%E6%B7%BB%E5%8A%A0%E5%88%AB%E5%90%8Dalias)\n    - [我想缓存一个仓库(repository)的用户名和密码](#%E6%88%91%E6%83%B3%E7%BC%93%E5%AD%98%E4%B8%80%E4%B8%AA%E4%BB%93%E5%BA%93repository%E7%9A%84%E7%94%A8%E6%88%B7%E5%90%8D%E5%92%8C%E5%AF%86%E7%A0%81)\n  - [我不知道我做错了些什么](#%E6%88%91%E4%B8%8D%E7%9F%A5%E9%81%93%E6%88%91%E5%81%9A%E9%94%99%E4%BA%86%E4%BA%9B%E4%BB%80%E4%B9%88)\n- [其它资源(Other Resources)](#%E5%85%B6%E5%AE%83%E8%B5%84%E6%BA%90other-resources)\n  - [书(Books)](#%E4%B9%A6books)\n  - [教程(Tutorials)](#%E6%95%99%E7%A8%8Btutorials)\n  - [脚本和工具(Scripts and Tools)](#%E8%84%9A%E6%9C%AC%E5%92%8C%E5%B7%A5%E5%85%B7scripts-and-tools)\n  - [GUI客户端(GUI Clients)](#gui%E5%AE%A2%E6%88%B7%E7%AB%AFgui-clients)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n## 编辑提交(editting commits)\n\n<a name=\"diff-last\"></a>\n### 我刚才提交了什么?\n\n如果你用 `git commit -a` 提交了一次变化(changes)，而你又不确定到底这次提交了哪些内容。 你就可以用下面的命令显示当前`HEAD`上的最近一次的提交(commit):\n\n```sh\n(main)$ git show\n```\n\n或者\n\n```sh\n$ git log -n1 -p\n```\n\n<a name=\"wrong-thing-in-commit-message\"></a>\n### 我的提交信息(commit message)写错了\n\n如果你的提交信息(commit message)写错了且这次提交(commit)还没有推(push), 你可以通过下面的方法来修改提交信息(commit message):\n\n```sh\n$ git commit --amend --only\n```\n这会打开你的默认编辑器, 在这里你可以编辑信息. 另一方面, 你也可以用一条命令一次完成:\n\n```sh\n$ git commit --amend --only -m 'xxxxxxx'\n```\n\n如果你已经推(push)了这次提交(commit), 你可以修改这次提交(commit)然后强推(force push), 但是不推荐这么做。\n\n<a name=\"commit-wrong-author\"></a>\n### 我提交(commit)里的用户名和邮箱不对\n\n如果这只是单个提交(commit)，修改它：\n\n```sh\n$ git commit --amend --author \"New Authorname <authoremail@mydomain.com>\"\n```\n\n如果你需要修改所有历史, 参考 'git filter-branch'的指南页.\n\n<a name=\"remove-file-from-commit\"></a>\n### 我想从一个提交(commit)里移除一个文件\n\n通过下面的方法，从一个提交(commit)里移除一个文件:\n\n```sh\n$ git checkout HEAD^ myfile\n$ git add -A\n$ git commit --amend\n```\n\n这将非常有用，当你有一个开放的补丁(open patch)，你往上面提交了一个不必要的文件，你需要强推(force push)去更新这个远程补丁。\n\n<a name=\"delete-pushed-commit\"></a>\n### 我想删除我的的最后一次提交(commit)\n\n如果你需要删除推了的提交(pushed commits)，你可以使用下面的方法。可是，这会不可逆的改变你的历史，也会搞乱那些已经从该仓库拉取(pulled)了的人的历史。简而言之，如果你不是很确定，千万不要这么做。\n\n```sh\n$ git reset HEAD^ --hard\n$ git push -f [remote] [branch]\n```\n\n如果你还没有推到远程, 把Git重置(reset)到你最后一次提交前的状态就可以了(同时保存暂存的变化):\n\n```\n(my-branch)$ git reset --soft HEAD^\n```\n\n这只能在没有推送之前有用. 如果你已经推了, 唯一安全能做的是 `git revert SHAofBadCommit`， 那会创建一个新的提交(commit)用于撤消前一个提交的所有变化(changes)； 或者, 如果你推的这个分支是rebase-safe的 (例如： 其它开发者不会从这个分支拉), 只需要使用 `git push -f`； 更多, 请参考 [the above section](#deleteremove-last-pushed-commit)。\n\n<a name=\"delete-any-commit\"></a>\n### 删除任意提交(commit)\n\n同样的警告：不到万不得已的时候不要这么做.\n\n```sh\n$ git rebase --onto SHA1_OF_BAD_COMMIT^ SHA1_OF_BAD_COMMIT\n$ git push -f [remote] [branch]\n```\n\n或者做一个 [交互式rebase](#interactive-rebase) 删除那些你想要删除的提交(commit)里所对应的行。\n\n<a name=\"force-push\"></a>\n### 我尝试推一个修正后的提交(amended commit)到远程，但是报错：\n\n```sh\nTo https://github.com/yourusername/repo.git\n! [rejected]        mybranch -> mybranch (non-fast-forward)\nerror: failed to push some refs to 'https://github.com/tanay1337/webmaker.org.git'\nhint: Updates were rejected because the tip of your current branch is behind\nhint: its remote counterpart. Integrate the remote changes (e.g.\nhint: 'git pull ...') before pushing again.\nhint: See the 'Note about fast-forwards' in 'git push --help' for details.\n```\n\n注意, rebasing(见下面)和修正(amending)会用一个**新的提交(commit)代替旧的**, 所以如果之前你已经往远程仓库上推过一次修正前的提交(commit)，那你现在就必须强推(force push) (`-f`)。 注意 &ndash; *总是* 确保你指明一个分支!\n\n```sh\n(my-branch)$ git push origin mybranch -f\n```\n\n一般来说, **要避免强推**. 最好是创建和推(push)一个新的提交(commit)，而不是强推一个修正后的提交。后者会使那些与该分支或该分支的子分支工作的开发者，在源历史中产生冲突。\n\n<a name=\"undo-git-reset-hard\"></a>\n### 我意外的做了一次硬重置(hard reset)，我想找回我的内容\n\n如果你意外的做了 `git reset --hard`, 你通常能找回你的提交(commit), 因为Git对每件事都会有日志，且都会保存几天。\n\n```sh\n(main)$ git reflog\n```\n\n你将会看到一个你过去提交(commit)的列表, 和一个重置的提交。 选择你想要回到的提交(commit)的SHA，再重置一次:\n\n```sh\n(main)$ git reset --hard SHA1234\n```\n\n这样就完成了。\n\n## 暂存(Staging)\n\n<a name=\"add-staged-changes-to-previous-commit\"></a>\n### 我需要把暂存的内容添加到上一次的提交(commit)\n\n```sh\n(my-branch*)$ git commit --amend\n\n```\n\n<a name=\"commit-partial-new-file\"></a>\n### 我想要暂存一个新文件的一部分，而不是这个文件的全部\n\n一般来说, 如果你想暂存一个文件的一部分, 你可这样做:\n\n```sh\n$ git add --patch filename.x\n```\n\n`-p` 简写。这会打开交互模式， 你将能够用 `s` 选项来分隔提交(commit)； 然而, 如果这个文件是新的, 会没有这个选择， 添加一个新文件时, 这样做:\n\n```sh\n$ git add -N filename.x\n```\n\n然后, 你需要用 `e` 选项来手动选择需要添加的行，执行 `git diff --cached` 将会显示哪些行暂存了哪些行只是保存在本地了。\n\n<a name=\"stage-in-two-commits\"></a>\n### 我想把在一个文件里的变化(changes)加到两个提交(commit)里\n\n`git add` 会把整个文件加入到一个提交. `git add -p` 允许交互式的选择你想要提交的部分.\n\n<a name=\"unstaging-edits-and-staging-the-unstaged\"></a>\n### 我想把暂存的内容变成未暂存，把未暂存的内容暂存起来\n\n多数情况下，你应该将所有的内容变为未暂存，然后再选择你想要的内容进行commit。\n但假定你就是想要这么做，这里你可以创建一个临时的commit来保存你已暂存的内容，然后暂存你的未暂存的内容并进行stash。然后reset最后一个commit将原本暂存的内容变为未暂存，最后stash pop回来。\n\n```sh\n$ git commit -m \"WIP\"\n$ git add .\n$ git stash\n$ git reset HEAD^\n$ git stash pop --index 0\n```\n\n注意1: 这里使用`pop`仅仅是因为想尽可能保持幂等。\n注意2: 假如你不加上`--index`你会把暂存的文件标记为为存储.这个[链接](https://stackoverflow.com/questions/31595873/git-stash-with-staged-files-does-stash-convert-staged-files-to-unstaged?answertab=active#tab-top) 解释得比较清楚。（不过是英文的，其大意是说，这是一个较为底层的问题，stash时会做2个commit，其中一个会记录index状态，staged的文件等东西，另一个记录worktree和其他的一些东西，如果你不在apply时加index，git会把两个一起销毁，所以staged里就空了）。\n\n## 未暂存(Unstaged)的内容\n\n<a name=\"move-unstaged-edits-to-new-branch\"></a>\n### 我想把未暂存的内容移动到一个新分支\n\n```sh\n$ git checkout -b my-branch\n```\n\n<a name=\"move-unstaged-edits-to-old-branch\"></a>\n### 我想把未暂存的内容移动到另一个已存在的分支\n\n```sh\n$ git stash\n$ git checkout my-branch\n$ git stash pop\n```\n\n<a name=\"discard-local-uncommitted-changes\"></a>\n### 我想丢弃本地未提交的变化(uncommitted changes)\n\n如果你只是想重置源(origin)和你本地(local)之间的一些提交(commit)，你可以：\n\n```sh\n# one commit\n(my-branch)$ git reset --hard HEAD^\n# two commits\n(my-branch)$ git reset --hard HEAD^^\n# four commits\n(my-branch)$ git reset --hard HEAD~4\n# or\n(main)$ git checkout -f\n```\n\n重置某个特殊的文件, 你可以用文件名做为参数:\n\n```sh\n$ git reset filename\n```\n\n<a name=\"discard-specific-unstaged-changes\"></a>\n### 我想丢弃某些未暂存的内容\n\n如果你想丢弃工作拷贝中的一部分内容，而不是全部。\n\n签出(checkout)不需要的内容，保留需要的。\n\n```sh\n$ git checkout -p\n# Answer y to all of the snippets you want to drop\n```\n\n另外一个方法是使用 `stash`， Stash所有要保留下的内容, 重置工作拷贝, 重新应用保留的部分。\n\n```sh\n$ git stash -p\n# Select all of the snippets you want to save\n$ git reset --hard\n$ git stash pop\n```\n\n或者, stash 你不需要的部分, 然后stash drop。\n\n```sh\n$ git stash -p\n# Select all of the snippets you don't want to save\n$ git stash drop\n```\n\n## 分支(Branches)\n\n<a name=\"pull-wrong-branch\"></a>\n### 我从错误的分支拉取了内容，或把内容拉取到了错误的分支\n\n这是另外一种使用 `git reflog` 情况，找到在这次错误拉(pull) 之前HEAD的指向。\n\n```sh\n(main)$ git reflog\nab7555f HEAD@{0}: pull origin wrong-branch: Fast-forward\nc5bc55a HEAD@{1}: checkout: checkout message goes here\n```\n\n重置分支到你所需的提交(desired commit):\n\n```sh\n$ git reset --hard c5bc55a\n```\n\n完成。\n\n<a name=\"discard-local-commits\"></a>\n### 我想扔掉本地的提交(commit)，以便我的分支与远程的保持一致\n\n先确认你没有推(push)你的内容到远程。\n\n`git status` 会显示你领先(ahead)源(origin)多少个提交:\n\n```sh\n(my-branch)$ git status\n# On branch my-branch\n# Your branch is ahead of 'origin/my-branch' by 2 commits.\n#   (use \"git push\" to publish your local commits)\n#\n```\n\n一种方法是:\n\n```sh\n(my-branch)$ git reset --hard origin/my-branch\n```\n\n<a name=\"commit-wrong-branch\"></a>\n### 我需要提交到一个新分支，但错误的提交到了main\n\n在main下创建一个新分支，不切换到新分支,仍在main下:\n\n```sh\n(main)$ git branch my-branch\n```\n\n把main分支重置到前一个提交:\n\n```sh\n(main)$ git reset --hard HEAD^\n```\n\n`HEAD^` 是 `HEAD^1` 的简写，你可以通过指定要设置的`HEAD`来进一步重置。\n\n或者, 如果你不想使用 `HEAD^`, 找到你想重置到的提交(commit)的hash(`git log` 能够完成)， 然后重置到这个hash。 使用`git push` 同步内容到远程。\n\n例如, main分支想重置到的提交的hash为`a13b85e`:\n\n```sh\n(main)$ git reset --hard a13b85e\nHEAD is now at a13b85e\n```\n\n签出(checkout)刚才新建的分支继续工作:\n\n```sh\n(main)$ git checkout my-branch\n```\n\n<a name=\"keep-whole-file\"></a>\n### 我想保留来自另外一个ref-ish的整个文件\n\n假设你正在做一个原型方案(原文为working spike (see note)), 有成百的内容，每个都工作得很好。现在, 你提交到了一个分支，保存工作内容:\n\n```sh\n(solution)$ git add -A && git commit -m \"Adding all changes from this spike into one big commit.\"\n```\n\n当你想要把它放到一个分支里 (可能是`feature`, 或者 `develop`), 你关心是保持整个文件的完整，你想要一个大的提交分隔成比较小。\n\n假设你有:\n\n  * 分支 `solution`, 拥有原型方案， 领先 `develop` 分支。\n  * 分支 `develop`, 在这里你应用原型方案的一些内容。\n\n我去可以通过把内容拿到你的分支里，来解决这个问题:\n\n```sh\n(develop)$ git checkout solution -- file1.txt\n```\n\n这会把这个文件内容从分支 `solution` 拿到分支 `develop` 里来:\n\n```sh\n# On branch develop\n# Your branch is up-to-date with 'origin/develop'.\n# Changes to be committed:\n#  (use \"git reset HEAD <file>...\" to unstage)\n#\n#        modified:   file1.txt\n```\n\n然后, 正常提交。\n\nNote: Spike solutions are made to analyze or solve the problem. These solutions are used for estimation and discarded once everyone gets clear visualization of the problem. ~ [Wikipedia](https://en.wikipedia.org/wiki/Extreme_programming_practices).\n\n<a name=\"cherry-pick\"></a>\n### 我把几个提交(commit)提交到了同一个分支，而这些提交应该分布在不同的分支里\n\n假设你有一个`main`分支， 执行`git log`, 你看到你做过两次提交:\n\n```sh\n(main)$ git log\n\ncommit e3851e817c451cc36f2e6f3049db528415e3c114\nAuthor: Alex Lee <alexlee@example.com>\nDate:   Tue Jul 22 15:39:27 2014 -0400\n\n    Bug #21 - Added CSRF protection\n\ncommit 5ea51731d150f7ddc4a365437931cd8be3bf3131\nAuthor: Alex Lee <alexlee@example.com>\nDate:   Tue Jul 22 15:39:12 2014 -0400\n\n    Bug #14 - Fixed spacing on title\n\ncommit a13b85e984171c6e2a1729bb061994525f626d14\nAuthor: Aki Rose <akirose@example.com>\nDate:   Tue Jul 21 01:12:48 2014 -0400\n\n    First commit\n```\n\n让我们用提交hash(commit hash)标记bug (`e3851e8` for #21, `5ea5173` for #14).\n\n首先, 我们把`main`分支重置到正确的提交(`a13b85e`):\n\n```sh\n(main)$ git reset --hard a13b85e\nHEAD is now at a13b85e\n```\n\n现在, 我们对 bug #21 创建一个新的分支:\n\n```sh\n(main)$ git checkout -b 21\n(21)$\n```\n\n接着, 我们用 *cherry-pick* 把对bug #21的提交放入当前分支。 这意味着我们将应用(apply)这个提交(commit)，仅仅这一个提交(commit)，直接在HEAD上面。\n\n```sh\n(21)$ git cherry-pick e3851e8\n```\n\n这时候, 这里可能会产生冲突， 参见[交互式 rebasing 章](#interactive-rebase) [**冲突节**](#merge-conflict) 解决冲突.\n\n再者， 我们为bug #14 创建一个新的分支, 也基于`main`分支\n\n```sh\n(21)$ git checkout main\n(main)$ git checkout -b 14\n(14)$\n```\n\n最后, 为 bug #14 执行 `cherry-pick`:\n\n```sh\n(14)$ git cherry-pick 5ea5173\n```\n\n<a name=\"delete-stale-local-branches\"></a>\n### 我想删除上游(upstream)分支被删除了的本地分支\n一旦你在github 上面合并(merge)了一个pull request, 你就可以删除你fork里被合并的分支。 如果你不准备继续在这个分支里工作, 删除这个分支的本地拷贝会更干净，使你不会陷入工作分支和一堆陈旧分支的混乱之中。\n\n```sh\n$ git fetch -p\n```\n\n<a name=\"restore-a-deleted-branch\"></a>\n### 我不小心删除了我的分支\n\n如果你定期推送到远程, 多数情况下应该是安全的，但有些时候还是可能删除了还没有推到远程的分支。 让我们先创建一个分支和一个新的文件:\n\n```sh\n(main)$ git checkout -b my-branch\n(my-branch)$ git branch\n(my-branch)$ touch foo.txt\n(my-branch)$ ls\nREADME.md foo.txt\n```\n\n添加文件并做一次提交\n\n```sh\n(my-branch)$ git add .\n(my-branch)$ git commit -m 'foo.txt added'\n(my-branch)$ foo.txt added\n 1 files changed, 1 insertions(+)\n create mode 100644 foo.txt\n(my-branch)$ git log\n\ncommit 4e3cd85a670ced7cc17a2b5d8d3d809ac88d5012\nAuthor: siemiatj <siemiatj@example.com>\nDate:   Wed Jul 30 00:34:10 2014 +0200\n\n    foo.txt added\n\ncommit 69204cdf0acbab201619d95ad8295928e7f411d5\nAuthor: Kate Hudson <katehudson@example.com>\nDate:   Tue Jul 29 13:14:46 2014 -0400\n\n    Fixes #6: Force pushing after amending commits\n```\n\n现在我们切回到主(main)分支，‘不小心的’删除`my-branch`分支\n\n```sh\n(my-branch)$ git checkout main\nSwitched to branch 'main'\nYour branch is up-to-date with 'origin/main'.\n(main)$ git branch -D my-branch\nDeleted branch my-branch (was 4e3cd85).\n(main)$ echo oh noes, deleted my branch!\noh noes, deleted my branch!\n```\n\n在这时候你应该想起了`reflog`, 一个升级版的日志，它存储了仓库(repo)里面所有动作的历史。\n\n```\n(main)$ git reflog\n69204cd HEAD@{0}: checkout: moving from my-branch to main\n4e3cd85 HEAD@{1}: commit: foo.txt added\n69204cd HEAD@{2}: checkout: moving from main to my-branch\n```\n\n正如你所见，我们有一个来自删除分支的提交hash(commit hash)，接下来看看是否能恢复删除了的分支。\n\n```sh\n(main)$ git checkout -b my-branch-help\nSwitched to a new branch 'my-branch-help'\n(my-branch-help)$ git reset --hard 4e3cd85\nHEAD is now at 4e3cd85 foo.txt added\n(my-branch-help)$ ls\nREADME.md foo.txt\n```\n\n看! 我们把删除的文件找回来了。 Git的 `reflog` 在rebasing出错的时候也是同样有用的。\n\n<a name=\"delete-branch\"></a>\n### 我想删除一个分支\n\n删除一个远程分支:\n\n```sh\n(main)$ git push origin --delete my-branch\n```\n\n你也可以:\n\n```sh\n(main)$ git push origin :my-branch\n```\n\n删除一个本地分支:\n\n```sh\n(main)$ git branch -D my-branch\n```\n\n<a name=\"working-on-checkout-remote-branch\"></a>\n### 我想从别人正在工作的远程分支签出(checkout)一个分支\n\n首先, 从远程拉取(fetch) 所有分支:\n\n```sh\n(main)$ git fetch --all\n```\n\n假设你想要从远程的`daves`分支签出到本地的`daves`\n\n```sh\n(main)$ git checkout --track origin/daves\nBranch daves set up to track remote branch daves from origin.\nSwitched to a new branch 'daves'\n```\n\n(`--track` 是 `git checkout -b [branch] [remotename]/[branch]` 的简写)\n\n这样就得到了一个`daves`分支的本地拷贝, 任何推过(pushed)的更新，远程都能看到.\n\n## Rebasing 和合并(Merging)\n\n<a name=\"undo-rebase\"></a>\n### 我想撤销rebase/merge\n\n你可以合并(merge)或rebase了一个错误的分支, 或者完成不了一个进行中的rebase/merge。 Git 在进行危险操作的时候会把原始的HEAD保存在一个叫ORIG_HEAD的变量里, 所以要把分支恢复到rebase/merge前的状态是很容易的。\n\n```sh\n(my-branch)$ git reset --hard ORIG_HEAD\n```\n\n<a name=\"force-push-rebase\"></a>\n### 我已经rebase过, 但是我不想强推(force push)\n\n不幸的是，如果你想把这些变化(changes)反应到远程分支上，你就必须得强推(force push)。 是因你快进(Fast forward)了提交，改变了Git历史, 远程分支不会接受变化(changes)，除非强推(force push)。这就是许多人使用 merge 工作流, 而不是 rebasing 工作流的主要原因之一， 开发者的强推(force push)会使大的团队陷入麻烦。使用时需要注意，一种安全使用 rebase 的方法是，不要把你的变化(changes)反映到远程分支上, 而是按下面的做:\n\n```sh\n(main)$ git checkout my-branch\n(my-branch)$ git rebase -i main\n(my-branch)$ git checkout main\n(main)$ git merge --ff-only my-branch\n```\n\n更多, 参见 [this SO thread](http://stackoverflow.com/questions/11058312/how-can-i-use-git-rebase-without-requiring-a-forced-push).\n\n<a name=\"interactive-rebase\"></a>\n### 我需要组合(combine)几个提交(commit)\n\n假设你的工作分支将会做对于 `main` 的pull-request。 一般情况下你不关心提交(commit)的时间戳，只想组合 *所有* 提交(commit) 到一个单独的里面, 然后重置(reset)重提交(recommit)。 确保主(main)分支是最新的和你的变化都已经提交了, 然后:\n\n```sh\n(my-branch)$ git reset --soft main\n(my-branch)$ git commit -am \"New awesome feature\"\n```\n\n如果你想要更多的控制, 想要保留时间戳, 你需要做交互式rebase (interactive rebase):\n\n```sh\n(my-branch)$ git rebase -i main\n```\n\n如果没有相对的其它分支， 你将不得不相对自己的`HEAD` 进行 rebase。 例如：你想组合最近的两次提交(commit), 你将相对于`HEAD~2` 进行rebase， 组合最近3次提交(commit), 相对于`HEAD~3`, 等等。\n\n```sh\n(main)$ git rebase -i HEAD~2\n```\n\n在你执行了交互式 rebase的命令(interactive rebase command)后, 你将在你的编辑器里看到类似下面的内容:\n\n```vim\npick a9c8a1d Some refactoring\npick 01b2fd8 New awesome feature\npick b729ad5 fixup\npick e3851e8 another fix\n\n# Rebase 8074d12..b729ad5 onto 8074d12\n#\n# Commands:\n#  p, pick = use commit\n#  r, reword = use commit, but edit the commit message\n#  e, edit = use commit, but stop for amending\n#  s, squash = use commit, but meld into previous commit\n#  f, fixup = like \"squash\", but discard this commit's log message\n#  x, exec = run command (the rest of the line) using shell\n#\n# These lines can be re-ordered; they are executed from top to bottom.\n#\n# If you remove a line here THAT COMMIT WILL BE LOST.\n#\n# However, if you remove everything, the rebase will be aborted.\n#\n# Note that empty commits are commented out\n```\n\n所有以 `#` 开头的行都是注释, 不会影响 rebase.\n\n然后，你可以用任何上面命令列表的命令替换 `pick`, 你也可以通过删除对应的行来删除一个提交(commit)。\n\n例如, 如果你想 **单独保留最旧(first)的提交(commit),组合所有剩下的到第二个里面**, 你就应该编辑第二个提交(commit)后面的每个提交(commit) 前的单词为 `f`:\n\n```vim\npick a9c8a1d Some refactoring\npick 01b2fd8 New awesome feature\nf b729ad5 fixup\nf e3851e8 another fix\n```\n\n如果你想组合这些提交(commit) **并重命名这个提交(commit)**, 你应该在第二个提交(commit)旁边添加一个`r`，或者更简单的用`s` 替代 `f`:\n\n```vim\npick a9c8a1d Some refactoring\npick 01b2fd8 New awesome feature\ns b729ad5 fixup\ns e3851e8 another fix\n```\n\n你可以在接下来弹出的文本提示框里重命名提交(commit)。\n\n```vim\nNewer, awesomer features\n\n# Please enter the commit message for your changes. Lines starting\n# with '#' will be ignored, and an empty message aborts the commit.\n# rebase in progress; onto 8074d12\n# You are currently editing a commit while rebasing branch 'main' on '8074d12'.\n#\n# Changes to be committed:\n#\tmodified:   README.md\n#\n\n```\n\n如果成功了, 你应该看到类似下面的内容:\n\n```sh\n(main)$ Successfully rebased and updated refs/heads/main.\n```\n\n#### 安全合并(merging)策略\n`--no-commit` 执行合并(merge)但不自动提交, 给用户在做提交前检查和修改的机会。 `no-ff` 会为特性分支(feature branch)的存在过留下证据, 保持项目历史一致。\n\n```sh\n(main)$ git merge --no-ff --no-commit my-branch\n```\n\n#### 我需要将一个分支合并成一个提交(commit)\n\n```sh\n(main)$ git merge --squash my-branch\n```\n\n<a name=\"rebase-unpushed-commits\"></a>\n#### 我只想组合(combine)未推的提交(unpushed commit)\n\n有时候，在将数据推向上游之前，你有几个正在进行的工作提交(commit)。这时候不希望把已经推(push)过的组合进来，因为其他人可能已经有提交(commit)引用它们了。\n\n```sh\n(main)$ git rebase -i @{u}\n```\n\n这会产生一次交互式的rebase(interactive rebase), 只会列出没有推(push)的提交(commit)， 在这个列表时进行reorder/fix/squash 都是安全的。\n\n<a name=\"check-if-all-commits-on-a-branch-are-merged\"></a>\n### 检查是否分支上的所有提交(commit)都合并(merge)过了\n\n检查一个分支上的所有提交(commit)是否都已经合并(merge)到了其它分支, 你应该在这些分支的head(或任何 commits)之间做一次diff:\n\n```sh\n(main)$ git log --graph --left-right --cherry-pick --oneline HEAD...feature/120-on-scroll\n```\n\n这会告诉你在一个分支里有而另一个分支没有的所有提交(commit), 和分支之间不共享的提交(commit)的列表。 另一个做法可以是:\n\n```sh\n(main)$ git log main ^feature/120-on-scroll --no-merges\n```\n\n### 交互式rebase(interactive rebase)可能出现的问题\n\n<a name=\"noop\"></a>\n#### 这个rebase 编辑屏幕出现'noop'\n\n如果你看到的是这样:\n```\nnoop\n```\n\n这意味着你rebase的分支和当前分支在同一个提交(commit)上, 或者 *领先(ahead)* 当前分支。 你可以尝试:\n\n* 检查确保主(main)分支没有问题\n* rebase  `HEAD~2` 或者更早\n\n<a name=\"merge-conflict\"></a>\n#### 有冲突的情况\n\n如果你不能成功的完成rebase, 你可能必须要解决冲突。\n\n首先执行 `git status` 找出哪些文件有冲突:\n\n```sh\n(my-branch)$ git status\nOn branch my-branch\nChanges not staged for commit:\n  (use \"git add <file>...\" to update what will be committed)\n  (use \"git checkout -- <file>...\" to discard changes in working directory)\n\n\tmodified:   README.md\n```\n\n在这个例子里面, `README.md` 有冲突。 打开这个文件找到类似下面的内容:\n\n```vim\n   <<<<<<< HEAD\n   some code\n   =========\n   some code\n   >>>>>>> new-commit\n```\n\n你需要解决新提交的代码(示例里, 从中间`==`线到`new-commit`的地方)与`HEAD` 之间不一样的地方.\n\n有时候这些合并非常复杂，你应该使用可视化的差异编辑器(visual diff editor):\n\n```sh\n(main*)$ git mergetool -t opendiff\n```\n\n在你解决完所有冲突和测试过后, `git add` 变化了的(changed)文件, 然后用`git rebase --continue` 继续rebase。\n\n```sh\n(my-branch)$ git add README.md\n(my-branch)$ git rebase --continue\n```\n\n如果在解决完所有的冲突过后，得到了与提交前一样的结果, 可以执行`git rebase --skip`。\n\n任何时候你想结束整个rebase 过程，回来rebase前的分支状态, 你可以做:\n\n```sh\n(my-branch)$ git rebase --abort\n```\n\n<a name=\"stashing\"></a>\n## Stash\n\n### 暂存所有改动\n\n暂存你工作目录下的所有改动\n\n```sh\n$ git stash\n```\n\n你可以使用`-u`来排除一些文件\n\n```sh\n$ git stash -u\n```\n\n### 暂存指定文件\n\n假设你只想暂存某一个文件\n\n```sh\n$ git stash push working-directory-path/filename.ext\n```\n\n假设你想暂存多个文件\n\n```sh\n$ git stash push working-directory-path/filename1.ext working-directory-path/filename2.ext\n```\n\n<a name=\"stash-msg\"></a>\n### 暂存时记录消息\n\n这样你可以在`list`时看到它\n\n```sh\n$ git stash save <message>\n```\n或\n```sh\n$ git stash push -m <message>\n```\n<a name=\"stash-apply-specific\"></a>\n### 使用某个指定暂存\n\n首先你可以查看你的`stash`记录\n\n```sh\n$ git stash list\n```\n\n然后你可以`apply`某个`stash`\n\n```sh\n$ git stash apply \"stash@{n}\"\n```\n\n此处， 'n'是`stash`在栈中的位置，最上层的`stash`会是0\n\n除此之外，也可以使用时间标记(假如你能记得的话)。\n\n```sh\n$ git stash apply \"stash@{2.hours.ago}\"\n```\n\n<a name=\"stage-and-keep-unstaged\"></a>\n### 暂存时保留未暂存的内容\n\n你需要手动create一个`stash commit`， 然后使用`git stash store`。\n\n```sh\n$ git stash create\n$ git stash store -m \"commit-message\" CREATED_SHA1\n```\n\n<a name=\"miscellaneous-objects\"></a>\n## 杂项(Miscellaneous Objects)\n\n<a name=\"clone-submodules\"></a>\n### 克隆所有子模块\n\n```sh\n$ git clone --recursive git://github.com/foo/bar.git\n```\n\n如果已经克隆了:\n\n```sh\n$ git submodule update --init --recursive\n```\n\n<a name=\"delete-tag\"></a>\n### 删除标签(tag)\n\n```sh\n$ git tag -d <tag_name>\n$ git push <remote> :refs/tags/<tag_name>\n```\n\n<a name=\"recover-tag\"></a>\n### 恢复已删除标签(tag)\n\n如果你想恢复一个已删除标签(tag), 可以按照下面的步骤: 首先, 需要找到无法访问的标签(unreachable tag):\n\n```sh\n$ git fsck --unreachable | grep tag\n```\n\n记下这个标签(tag)的hash，然后用Git的 [update-ref](http://git-scm.com/docs/git-update-ref):\n\n```sh\n$ git update-ref refs/tags/<tag_name> <hash>\n```\n\n这时你的标签(tag)应该已经恢复了。\n\n<a name=\"deleted-patch\"></a>\n### 已删除补丁(patch)\n\n如果某人在 GitHub 上给你发了一个pull request, 但是然后他删除了他自己的原始 fork, 你将没法克隆他们的提交(commit)或使用 `git am`。在这种情况下, 最好手动的查看他们的提交(commit)，并把它们拷贝到一个本地新分支，然后做提交。\n\n做完提交后, 再修改作者，参见[变更作者](#commit-wrong-author)。 然后, 应用变化, 再发起一个新的pull request。\n\n## 跟踪文件(Tracking Files)\n\n<a name=\"change-file-name-capitalization-without-changing-contents\"></a>\n### 我只想改变一个文件名字的大小写，而不修改内容\n\n```sh\n(main)$ git mv --force myfile MyFile\n```\n\n<a name=\"remove-from-git\"></a>\n### 我想从Git删除一个文件，但保留该文件\n\n```sh\n(main)$ git rm --cached log.txt\n```\n\n## 配置(Configuration)\n\n<a name=\"adding-command-aliases\"></a>\n### 我想给一些Git命令添加别名(alias)\n\n在 OS X 和 Linux 下, 你的 Git的配置文件储存在 ```~/.gitconfig```。我在```[alias]``` 部分添加了一些快捷别名(和一些我容易拼写错误的)，如下:\n\n```vim\n[alias]\n    a = add\n    amend = commit --amend\n    c = commit\n    ca = commit --amend\n    ci = commit -a\n    co = checkout\n    d = diff\n    dc = diff --changed\n    ds = diff --staged\n    f = fetch\n    loll = log --graph --decorate --pretty=oneline --abbrev-commit\n    m = merge\n    one = log --pretty=oneline\n    outstanding = rebase -i @{u}\n    s = status\n    unpushed = log @{u}\n    wc = whatchanged\n    wip = rebase -i @{u}\n    zap = fetch -p\n```\n\n<a name=\"credential-helper\"></a>\n### 我想缓存一个仓库(repository)的用户名和密码\n\n你可能有一个仓库需要授权，这时你可以缓存用户名和密码，而不用每次推/拉(push/pull)的时候都输入，Credential helper能帮你。\n\n```sh\n$ git config --global credential.helper cache\n# Set git to use the credential memory cache\n```\n\n```sh\n$ git config --global credential.helper 'cache --timeout=3600'\n# Set the cache to timeout after 1 hour (setting is in seconds)\n```\n\n<a name=\"ive-no-idea-what-i-did-wrong\"></a>\n## 我不知道我做错了些什么\n\n你把事情搞砸了：你 `重置(reset)` 了一些东西, 或者你合并了错误的分支, 亦或你强推了后找不到你自己的提交(commit)了。有些时候, 你一直都做得很好, 但你想回到以前的某个状态。\n\n这就是 `git reflog` 的目的， `reflog` 记录对分支顶端(the tip of a branch)的任何改变, 即使那个顶端没有被任何分支或标签引用。基本上, 每次HEAD的改变, 一条新的记录就会增加到`reflog`。遗憾的是，这只对本地分支起作用，且它只跟踪动作 (例如，不会跟踪一个没有被记录的文件的任何改变)。\n\n```sh\n(main)$ git reflog\n0a2e358 HEAD@{0}: reset: moving to HEAD~2\n0254ea7 HEAD@{1}: checkout: moving from 2.2 to main\nc10f740 HEAD@{2}: checkout: moving from main to 2.2\n```\n\n上面的reflog展示了从main分支签出(checkout)到2.2 分支，然后再签回。 那里，还有一个硬重置(hard reset)到一个较旧的提交。最新的动作出现在最上面以 `HEAD@{0}`标识.\n\n如果事实证明你不小心回移(move back)了提交(commit), reflog 会包含你不小心回移前main上指向的提交(0254ea7)。\n\n```sh\n$ git reset --hard 0254ea7\n```\n\n然后使用git reset就可以把main改回到之前的commit，这提供了一个在历史被意外更改情况下的安全网。\n\n([摘自](https://www.atlassian.com/git/tutorials/rewriting-history/git-reflog)).\n\n# 其它资源(Other Resources)\n\n## 书(Books)\n\n* [Pro Git](https://git-scm.com/book/en/v2) - Scott Chacon's excellent git book\n* [Git Internals](https://github.com/pluralsight/git-internals-pdf) - Scott Chacon's other excellent git book\n\n## 教程(Tutorials)\n\n* [Learn Git branching](https://learngitbranching.js.org/) 一个基于网页的交互式 branching/merging/rebasing 教程\n* [Getting solid at Git rebase vs. merge](https://medium.com/@porteneuve/getting-solid-at-git-rebase-vs-merge-4fa1a48c53aa)\n* [git-workflow](https://github.com/asmeurer/git-workflow) - [Aaron Meurer](https://github.com/asmeurer)的怎么使用Git为开源仓库贡献\n* [GitHub as a workflow](http://hugogiraudel.com/2015/08/13/github-as-a-workflow/) - 使用GitHub做为工作流的趣事, 尤其是空PRs\n\n## 脚本和工具(Scripts and Tools)\n\n* [firstaidgit.io](http://firstaidgit.io/) 一个可搜索的最常被问到的Git的问题\n* [git-extra-commands](https://github.com/unixorn/git-extra-commands) - 一堆有用的额外的Git脚本\n* [git-extras](https://github.com/tj/git-extras) - GIT 工具集 -- repo summary, repl, changelog population, author commit percentages and more\n* [git-fire](https://github.com/qw3rtman/git-fire) - git-fire 是一个 Git 插件，用于帮助在紧急情况下添加所有当前文件, 做提交(committing), 和推(push)到一个新分支(阻止合并冲突)。\n* [git-tips](https://github.com/git-tips/tips) - Git小提示\n* [git-town](https://github.com/Originate/git-town) - 通用，高级Git工作流支持！ http://www.git-town.com\n\n## GUI客户端(GUI Clients)\n* [GitKraken](https://www.gitkraken.com/) - 豪华的Git客户端 Windows, Mac & Linux\n* [git-cola](https://git-cola.github.io/) - 另外一个Git客户端 Windows & OS X\n* [GitUp](https://github.com/git-up/GitUp) - 一个新的Git客户端，在处理Git的复杂性上有自己的特点\n* [gitx-dev](https://rowanj.github.io/gitx/) - 图形化的Git客户端 OS X\n* [Source Tree](https://www.sourcetreeapp.com/) - 免费的图形化Git客户端 Windows & OS X\n* [Tower](http://www.git-tower.com/) - 图形化Git客户端 OS X(付费)\n"
  },
  {
    "path": "README_zh-TW.md",
    "content": "# Git 飛行規則（Flight Rules）\n\n🌍\n*[English](README.md) ∙ [Español](README_es.md)  ∙  [Русский](README_ru.md) ∙ [繁體中文](README_zh-TW.md) ∙ [簡體中文](README_zh-CN.md) ∙ [한국어](README_kr.md)  ∙  [Tiếng Việt](README_vi.md) ∙ [Français](README_fr.md) ∙ [日本語](README_ja.md)*\n\n#### 前言\n\n- 英文原版 [README](https://github.com/k88hudson/git-flight-rules/blob/master/README.md)\n- 翻譯可能存在錯誤或不標準的地方，歡迎大家指正和修改，謝謝！\n\n#### 什麼是「飛行規則」？\n\n這是一篇給太空人（這裡就是指使用 Git 的程式設計師們）的指南，用來指導問題出現後的應對之法。\n\n> 飛行規則（flight rules）是記錄在手冊上的來之不易的一系列知識，記錄了某個事情發生的原因，以及怎樣一步一步的進行處理。本質上，它們是特定場景的非常詳細的標準處理流程。[...]\n\n> 自 20 世紀 60 年代初以來，NASA 一直在捕捉（capturing）失誤、災難和解決方案。當時水星時代（Mercury-era）的地面小組首先開始將「經驗教訓」收集到一個綱要（compendium）中，該綱現在已經有上千個問題情景，從發動機故障、到破損的艙口把手、再到計算機故障，以及它們對應的解決方案。\n\n——Chris Hadfield，《一個太空人的生活指南》（An Astronaut's Guide to Life）\n\n#### 這篇文章的約定\n\n為了清楚的表述，這篇文件裡的所有例子使用了自訂的 Bash 提示字元，以便指示目前分支和是否有暫存的更動。分支名用小括號括起來，分支名後面跟的 `*` 表示暫存的更動。\n\n[![Join the chat at https://gitter.im/k88hudson/git-flight-rules](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/k88hudson/git-flight-rules?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n  - [版本庫](#%E7%89%88%E6%9C%AC%E5%BA%AB)\n    - [我想建立本機版本庫](#%E6%88%91%E6%83%B3%E5%BB%BA%E7%AB%8B%E6%9C%AC%E6%A9%9F%E7%89%88%E6%9C%AC%E5%BA%AB)\n    - [我想複製遠端版本庫](#%E6%88%91%E6%83%B3%E8%A4%87%E8%A3%BD%E9%81%A0%E7%AB%AF%E7%89%88%E6%9C%AC%E5%BA%AB)\n    - [我設定了錯的遠端版本庫](#%E6%88%91%E8%A8%AD%E5%AE%9A%E4%BA%86%E9%8C%AF%E7%9A%84%E9%81%A0%E7%AB%AF%E7%89%88%E6%9C%AC%E5%BA%AB)\n    - [我想將程式碼加到其他人的版本庫中](#%E6%88%91%E6%83%B3%E5%B0%87%E7%A8%8B%E5%BC%8F%E7%A2%BC%E5%8A%A0%E5%88%B0%E5%85%B6%E4%BB%96%E4%BA%BA%E7%9A%84%E7%89%88%E6%9C%AC%E5%BA%AB%E4%B8%AD)\n      - [透過拉取請求建議程式碼](#%E9%80%8F%E9%81%8E%E6%8B%89%E5%8F%96%E8%AB%8B%E6%B1%82%E5%BB%BA%E8%AD%B0%E7%A8%8B%E5%BC%8F%E7%A2%BC)\n      - [透過修補建議程式碼](#%E9%80%8F%E9%81%8E%E4%BF%AE%E8%A3%9C%E5%BB%BA%E8%AD%B0%E7%A8%8B%E5%BC%8F%E7%A2%BC)\n      - [我需要將分叉更新到原版的最新進度](#%E6%88%91%E9%9C%80%E8%A6%81%E5%B0%87%E5%88%86%E5%8F%89%E6%9B%B4%E6%96%B0%E5%88%B0%E5%8E%9F%E7%89%88%E7%9A%84%E6%9C%80%E6%96%B0%E9%80%B2%E5%BA%A6)\n  - [編輯提交](#%E7%B7%A8%E8%BC%AF%E6%8F%90%E4%BA%A4)\n    - [我剛才提交了什麼？](#%E6%88%91%E5%89%9B%E6%89%8D%E6%8F%90%E4%BA%A4%E4%BA%86%E4%BB%80%E9%BA%BC)\n    - [我的提交訊息寫錯了](#%E6%88%91%E7%9A%84%E6%8F%90%E4%BA%A4%E8%A8%8A%E6%81%AF%E5%AF%AB%E9%8C%AF%E4%BA%86)\n    - [我提交裡的使用者名稱和信箱不對](#%E6%88%91%E6%8F%90%E4%BA%A4%E8%A3%A1%E7%9A%84%E4%BD%BF%E7%94%A8%E8%80%85%E5%90%8D%E7%A8%B1%E5%92%8C%E4%BF%A1%E7%AE%B1%E4%B8%8D%E5%B0%8D)\n    - [我想從一個提交裡移除一個檔案](#%E6%88%91%E6%83%B3%E5%BE%9E%E4%B8%80%E5%80%8B%E6%8F%90%E4%BA%A4%E8%A3%A1%E7%A7%BB%E9%99%A4%E4%B8%80%E5%80%8B%E6%AA%94%E6%A1%88)\n    - [我想將更動從一個提交移到另一個](#%E6%88%91%E6%83%B3%E5%B0%87%E6%9B%B4%E5%8B%95%E5%BE%9E%E4%B8%80%E5%80%8B%E6%8F%90%E4%BA%A4%E7%A7%BB%E5%88%B0%E5%8F%A6%E4%B8%80%E5%80%8B)\n    - [我想刪除我最後一次提交](#%E6%88%91%E6%83%B3%E5%88%AA%E9%99%A4%E6%88%91%E6%9C%80%E5%BE%8C%E4%B8%80%E6%AC%A1%E6%8F%90%E4%BA%A4)\n    - [刪除任意提交](#%E5%88%AA%E9%99%A4%E4%BB%BB%E6%84%8F%E6%8F%90%E4%BA%A4)\n    - [我嘗試推送一個修正後的提交到遠端，但是報錯](#%E6%88%91%E5%98%97%E8%A9%A6%E6%8E%A8%E9%80%81%E4%B8%80%E5%80%8B%E4%BF%AE%E6%AD%A3%E5%BE%8C%E7%9A%84%E6%8F%90%E4%BA%A4%E5%88%B0%E9%81%A0%E7%AB%AF%E4%BD%86%E6%98%AF%E5%A0%B1%E9%8C%AF)\n    - [我意外地硬性重設了，我想找回我的內容](#%E6%88%91%E6%84%8F%E5%A4%96%E5%9C%B0%E7%A1%AC%E6%80%A7%E9%87%8D%E8%A8%AD%E4%BA%86%E6%88%91%E6%83%B3%E6%89%BE%E5%9B%9E%E6%88%91%E7%9A%84%E5%85%A7%E5%AE%B9)\n    - [我意外地提交並推送了合併](#%E6%88%91%E6%84%8F%E5%A4%96%E5%9C%B0%E6%8F%90%E4%BA%A4%E4%B8%A6%E6%8E%A8%E9%80%81%E4%BA%86%E5%90%88%E4%BD%B5)\n    - [我意外地提交並推送了敏感資料](#%E6%88%91%E6%84%8F%E5%A4%96%E5%9C%B0%E6%8F%90%E4%BA%A4%E4%B8%A6%E6%8E%A8%E9%80%81%E4%BA%86%E6%95%8F%E6%84%9F%E8%B3%87%E6%96%99)\n    - [我想要從現有的版本庫歷史記錄中移除大檔案](#%E6%88%91%E6%83%B3%E8%A6%81%E5%BE%9E%E7%8F%BE%E6%9C%89%E7%9A%84%E7%89%88%E6%9C%AC%E5%BA%AB%E6%AD%B7%E5%8F%B2%E8%A8%98%E9%8C%84%E4%B8%AD%E7%A7%BB%E9%99%A4%E5%A4%A7%E6%AA%94%E6%A1%88)\n      - [推薦的工具：第三方的 BFG](#%E6%8E%A8%E8%96%A6%E7%9A%84%E5%B7%A5%E5%85%B7%E7%AC%AC%E4%B8%89%E6%96%B9%E7%9A%84-bfg)\n      - [內建的工具：`git filter-branch`](#%E5%85%A7%E5%BB%BA%E7%9A%84%E5%B7%A5%E5%85%B7git-filter-branch)\n      - [最後一步：推送你變更過的歷史](#%E6%9C%80%E5%BE%8C%E4%B8%80%E6%AD%A5%E6%8E%A8%E9%80%81%E4%BD%A0%E8%AE%8A%E6%9B%B4%E9%81%8E%E7%9A%84%E6%AD%B7%E5%8F%B2)\n    - [我需要變更非最新者的提交的內容](#%E6%88%91%E9%9C%80%E8%A6%81%E8%AE%8A%E6%9B%B4%E9%9D%9E%E6%9C%80%E6%96%B0%E8%80%85%E7%9A%84%E6%8F%90%E4%BA%A4%E7%9A%84%E5%85%A7%E5%AE%B9)\n  - [暫存](#%E6%9A%AB%E5%AD%98)\n    - [我想暫存所有追蹤的檔案](#%E6%88%91%E6%83%B3%E6%9A%AB%E5%AD%98%E6%89%80%E6%9C%89%E8%BF%BD%E8%B9%A4%E7%9A%84%E6%AA%94%E6%A1%88)\n      - [只暫存一部分追蹤的檔案](#%E5%8F%AA%E6%9A%AB%E5%AD%98%E4%B8%80%E9%83%A8%E5%88%86%E8%BF%BD%E8%B9%A4%E7%9A%84%E6%AA%94%E6%A1%88)\n    - [我需要把暫存的內容添加到上一次的提交](#%E6%88%91%E9%9C%80%E8%A6%81%E6%8A%8A%E6%9A%AB%E5%AD%98%E7%9A%84%E5%85%A7%E5%AE%B9%E6%B7%BB%E5%8A%A0%E5%88%B0%E4%B8%8A%E4%B8%80%E6%AC%A1%E7%9A%84%E6%8F%90%E4%BA%A4)\n    - [我想要暫存一個新檔案的一部分，而不是這個檔案的全部](#%E6%88%91%E6%83%B3%E8%A6%81%E6%9A%AB%E5%AD%98%E4%B8%80%E5%80%8B%E6%96%B0%E6%AA%94%E6%A1%88%E7%9A%84%E4%B8%80%E9%83%A8%E5%88%86%E8%80%8C%E4%B8%8D%E6%98%AF%E9%80%99%E5%80%8B%E6%AA%94%E6%A1%88%E7%9A%84%E5%85%A8%E9%83%A8)\n    - [我想把在一個檔案裡的更動加到兩個提交裡](#%E6%88%91%E6%83%B3%E6%8A%8A%E5%9C%A8%E4%B8%80%E5%80%8B%E6%AA%94%E6%A1%88%E8%A3%A1%E7%9A%84%E6%9B%B4%E5%8B%95%E5%8A%A0%E5%88%B0%E5%85%A9%E5%80%8B%E6%8F%90%E4%BA%A4%E8%A3%A1)\n    - [我暫存了太多更動，而想把它們分到多個提交中](#%E6%88%91%E6%9A%AB%E5%AD%98%E4%BA%86%E5%A4%AA%E5%A4%9A%E6%9B%B4%E5%8B%95%E8%80%8C%E6%83%B3%E6%8A%8A%E5%AE%83%E5%80%91%E5%88%86%E5%88%B0%E5%A4%9A%E5%80%8B%E6%8F%90%E4%BA%A4%E4%B8%AD)\n    - [我想把暫存的內容變成未暫存，把未暫存的內容暫存起來](#%E6%88%91%E6%83%B3%E6%8A%8A%E6%9A%AB%E5%AD%98%E7%9A%84%E5%85%A7%E5%AE%B9%E8%AE%8A%E6%88%90%E6%9C%AA%E6%9A%AB%E5%AD%98%E6%8A%8A%E6%9C%AA%E6%9A%AB%E5%AD%98%E7%9A%84%E5%85%A7%E5%AE%B9%E6%9A%AB%E5%AD%98%E8%B5%B7%E4%BE%86)\n  - [未暫存的更動](#%E6%9C%AA%E6%9A%AB%E5%AD%98%E7%9A%84%E6%9B%B4%E5%8B%95)\n    - [我想把未暫存的更動移動到新分支](#%E6%88%91%E6%83%B3%E6%8A%8A%E6%9C%AA%E6%9A%AB%E5%AD%98%E7%9A%84%E6%9B%B4%E5%8B%95%E7%A7%BB%E5%8B%95%E5%88%B0%E6%96%B0%E5%88%86%E6%94%AF)\n    - [我想把未暫存的更動移動到另一個現有分支](#%E6%88%91%E6%83%B3%E6%8A%8A%E6%9C%AA%E6%9A%AB%E5%AD%98%E7%9A%84%E6%9B%B4%E5%8B%95%E7%A7%BB%E5%8B%95%E5%88%B0%E5%8F%A6%E4%B8%80%E5%80%8B%E7%8F%BE%E6%9C%89%E5%88%86%E6%94%AF)\n    - [我想捨棄未提交的更動](#%E6%88%91%E6%83%B3%E6%8D%A8%E6%A3%84%E6%9C%AA%E6%8F%90%E4%BA%A4%E7%9A%84%E6%9B%B4%E5%8B%95)\n    - [我想捨棄某些未暫存的更動](#%E6%88%91%E6%83%B3%E6%8D%A8%E6%A3%84%E6%9F%90%E4%BA%9B%E6%9C%AA%E6%9A%AB%E5%AD%98%E7%9A%84%E6%9B%B4%E5%8B%95)\n  - [分支](#%E5%88%86%E6%94%AF)\n    - [我想列出所有分支](#%E6%88%91%E6%83%B3%E5%88%97%E5%87%BA%E6%89%80%E6%9C%89%E5%88%86%E6%94%AF)\n    - [我想從一個提交創建分支](#%E6%88%91%E6%83%B3%E5%BE%9E%E4%B8%80%E5%80%8B%E6%8F%90%E4%BA%A4%E5%89%B5%E5%BB%BA%E5%88%86%E6%94%AF)\n    - [我從錯誤的分支拉取，或拉取到錯誤的分支了](#%E6%88%91%E5%BE%9E%E9%8C%AF%E8%AA%A4%E7%9A%84%E5%88%86%E6%94%AF%E6%8B%89%E5%8F%96%E6%88%96%E6%8B%89%E5%8F%96%E5%88%B0%E9%8C%AF%E8%AA%A4%E7%9A%84%E5%88%86%E6%94%AF%E4%BA%86)\n    - [我想捨棄本機上的提交，以讓分支與遠端保持一致](#%E6%88%91%E6%83%B3%E6%8D%A8%E6%A3%84%E6%9C%AC%E6%A9%9F%E4%B8%8A%E7%9A%84%E6%8F%90%E4%BA%A4%E4%BB%A5%E8%AE%93%E5%88%86%E6%94%AF%E8%88%87%E9%81%A0%E7%AB%AF%E4%BF%9D%E6%8C%81%E4%B8%80%E8%87%B4)\n    - [我需要提交到一個新分支，但錯誤的提交到了 `main`](#%E6%88%91%E9%9C%80%E8%A6%81%E6%8F%90%E4%BA%A4%E5%88%B0%E4%B8%80%E5%80%8B%E6%96%B0%E5%88%86%E6%94%AF%E4%BD%86%E9%8C%AF%E8%AA%A4%E7%9A%84%E6%8F%90%E4%BA%A4%E5%88%B0%E4%BA%86-main)\n    - [我想從另一個引用之類保留整個檔案](#%E6%88%91%E6%83%B3%E5%BE%9E%E5%8F%A6%E4%B8%80%E5%80%8B%E5%BC%95%E7%94%A8%E4%B9%8B%E9%A1%9E%E4%BF%9D%E7%95%99%E6%95%B4%E5%80%8B%E6%AA%94%E6%A1%88)\n    - [我把在同一分支提交了幾次，而這些提交應該在不同的分支上](#%E6%88%91%E6%8A%8A%E5%9C%A8%E5%90%8C%E4%B8%80%E5%88%86%E6%94%AF%E6%8F%90%E4%BA%A4%E4%BA%86%E5%B9%BE%E6%AC%A1%E8%80%8C%E9%80%99%E4%BA%9B%E6%8F%90%E4%BA%A4%E6%87%89%E8%A9%B2%E5%9C%A8%E4%B8%8D%E5%90%8C%E7%9A%84%E5%88%86%E6%94%AF%E4%B8%8A)\n    - [我想刪除上游刪除了的本機分支](#%E6%88%91%E6%83%B3%E5%88%AA%E9%99%A4%E4%B8%8A%E6%B8%B8%E5%88%AA%E9%99%A4%E4%BA%86%E7%9A%84%E6%9C%AC%E6%A9%9F%E5%88%86%E6%94%AF)\n    - [我不小心刪除了分支](#%E6%88%91%E4%B8%8D%E5%B0%8F%E5%BF%83%E5%88%AA%E9%99%A4%E4%BA%86%E5%88%86%E6%94%AF)\n    - [我想刪除一個分支](#%E6%88%91%E6%83%B3%E5%88%AA%E9%99%A4%E4%B8%80%E5%80%8B%E5%88%86%E6%94%AF)\n    - [我想刪除多個分支](#%E6%88%91%E6%83%B3%E5%88%AA%E9%99%A4%E5%A4%9A%E5%80%8B%E5%88%86%E6%94%AF)\n    - [我想重新命名一個分支](#%E6%88%91%E6%83%B3%E9%87%8D%E6%96%B0%E5%91%BD%E5%90%8D%E4%B8%80%E5%80%8B%E5%88%86%E6%94%AF)\n    - [我想簽出別人正在其上工作的遠端分支](#%E6%88%91%E6%83%B3%E7%B0%BD%E5%87%BA%E5%88%A5%E4%BA%BA%E6%AD%A3%E5%9C%A8%E5%85%B6%E4%B8%8A%E5%B7%A5%E4%BD%9C%E7%9A%84%E9%81%A0%E7%AB%AF%E5%88%86%E6%94%AF)\n    - [我想從本機分支創建一個遠端的](#%E6%88%91%E6%83%B3%E5%BE%9E%E6%9C%AC%E6%A9%9F%E5%88%86%E6%94%AF%E5%89%B5%E5%BB%BA%E4%B8%80%E5%80%8B%E9%81%A0%E7%AB%AF%E7%9A%84)\n    - [我想設定本機分支的上游](#%E6%88%91%E6%83%B3%E8%A8%AD%E5%AE%9A%E6%9C%AC%E6%A9%9F%E5%88%86%E6%94%AF%E7%9A%84%E4%B8%8A%E6%B8%B8)\n    - [我想設定 `HEAD` 追蹤預設遠端分支](#%E6%88%91%E6%83%B3%E8%A8%AD%E5%AE%9A-head-%E8%BF%BD%E8%B9%A4%E9%A0%90%E8%A8%AD%E9%81%A0%E7%AB%AF%E5%88%86%E6%94%AF)\n    - [我在錯誤的分支上做了更動](#%E6%88%91%E5%9C%A8%E9%8C%AF%E8%AA%A4%E7%9A%84%E5%88%86%E6%94%AF%E4%B8%8A%E5%81%9A%E4%BA%86%E6%9B%B4%E5%8B%95)\n    - [我想將分支一分為二](#%E6%88%91%E6%83%B3%E5%B0%87%E5%88%86%E6%94%AF%E4%B8%80%E5%88%86%E7%82%BA%E4%BA%8C)\n  - [重定基底與合併](#%E9%87%8D%E5%AE%9A%E5%9F%BA%E5%BA%95%E8%88%87%E5%90%88%E4%BD%B5)\n    - [撤銷重定基底或合併](#%E6%92%A4%E9%8A%B7%E9%87%8D%E5%AE%9A%E5%9F%BA%E5%BA%95%E6%88%96%E5%90%88%E4%BD%B5)\n    - [我重定了基底，但我不想強制推送](#%E6%88%91%E9%87%8D%E5%AE%9A%E4%BA%86%E5%9F%BA%E5%BA%95%E4%BD%86%E6%88%91%E4%B8%8D%E6%83%B3%E5%BC%B7%E5%88%B6%E6%8E%A8%E9%80%81)\n    - [我需要組合幾個提交](#%E6%88%91%E9%9C%80%E8%A6%81%E7%B5%84%E5%90%88%E5%B9%BE%E5%80%8B%E6%8F%90%E4%BA%A4)\n      - [安全合併的策略](#%E5%AE%89%E5%85%A8%E5%90%88%E4%BD%B5%E7%9A%84%E7%AD%96%E7%95%A5)\n      - [我需要將整個分支合併成單一提交](#%E6%88%91%E9%9C%80%E8%A6%81%E5%B0%87%E6%95%B4%E5%80%8B%E5%88%86%E6%94%AF%E5%90%88%E4%BD%B5%E6%88%90%E5%96%AE%E4%B8%80%E6%8F%90%E4%BA%A4)\n      - [我只想組合未推送的提交](#%E6%88%91%E5%8F%AA%E6%83%B3%E7%B5%84%E5%90%88%E6%9C%AA%E6%8E%A8%E9%80%81%E7%9A%84%E6%8F%90%E4%BA%A4)\n      - [我需要中止合併](#%E6%88%91%E9%9C%80%E8%A6%81%E4%B8%AD%E6%AD%A2%E5%90%88%E4%BD%B5)\n    - [我需要更新分支的親代提交](#%E6%88%91%E9%9C%80%E8%A6%81%E6%9B%B4%E6%96%B0%E5%88%86%E6%94%AF%E7%9A%84%E8%A6%AA%E4%BB%A3%E6%8F%90%E4%BA%A4)\n    - [檢查分支上的所有提交是否都合併了](#%E6%AA%A2%E6%9F%A5%E5%88%86%E6%94%AF%E4%B8%8A%E7%9A%84%E6%89%80%E6%9C%89%E6%8F%90%E4%BA%A4%E6%98%AF%E5%90%A6%E9%83%BD%E5%90%88%E4%BD%B5%E4%BA%86)\n    - [互動式重定基底可能出現的問題](#%E4%BA%92%E5%8B%95%E5%BC%8F%E9%87%8D%E5%AE%9A%E5%9F%BA%E5%BA%95%E5%8F%AF%E8%83%BD%E5%87%BA%E7%8F%BE%E7%9A%84%E5%95%8F%E9%A1%8C)\n      - [編輯介面出現「noop」](#%E7%B7%A8%E8%BC%AF%E4%BB%8B%E9%9D%A2%E5%87%BA%E7%8F%BEnoop)\n      - [衝突](#%E8%A1%9D%E7%AA%81)\n  - [貯存](#%E8%B2%AF%E5%AD%98)\n    - [貯存所有更動](#%E8%B2%AF%E5%AD%98%E6%89%80%E6%9C%89%E6%9B%B4%E5%8B%95)\n    - [貯存指定檔案](#%E8%B2%AF%E5%AD%98%E6%8C%87%E5%AE%9A%E6%AA%94%E6%A1%88)\n    - [貯存時附加訊息](#%E8%B2%AF%E5%AD%98%E6%99%82%E9%99%84%E5%8A%A0%E8%A8%8A%E6%81%AF)\n    - [套用指定貯存](#%E5%A5%97%E7%94%A8%E6%8C%87%E5%AE%9A%E8%B2%AF%E5%AD%98)\n    - [貯存時保留未暫存的內容](#%E8%B2%AF%E5%AD%98%E6%99%82%E4%BF%9D%E7%95%99%E6%9C%AA%E6%9A%AB%E5%AD%98%E7%9A%84%E5%85%A7%E5%AE%B9)\n  - [尋找](#%E5%B0%8B%E6%89%BE)\n    - [我想找到引入特定字串的提交](#%E6%88%91%E6%83%B3%E6%89%BE%E5%88%B0%E5%BC%95%E5%85%A5%E7%89%B9%E5%AE%9A%E5%AD%97%E4%B8%B2%E7%9A%84%E6%8F%90%E4%BA%A4)\n    - [我想找到特定作者／提交者的提交](#%E6%88%91%E6%83%B3%E6%89%BE%E5%88%B0%E7%89%B9%E5%AE%9A%E4%BD%9C%E8%80%85%EF%BC%8F%E6%8F%90%E4%BA%A4%E8%80%85%E7%9A%84%E6%8F%90%E4%BA%A4)\n    - [我想找到包含特定檔案的提交](#%E6%88%91%E6%83%B3%E6%89%BE%E5%88%B0%E5%8C%85%E5%90%AB%E7%89%B9%E5%AE%9A%E6%AA%94%E6%A1%88%E7%9A%84%E6%8F%90%E4%BA%A4)\n    - [我想找到特定函式的歷史記錄](#%E6%88%91%E6%83%B3%E6%89%BE%E5%88%B0%E7%89%B9%E5%AE%9A%E5%87%BD%E5%BC%8F%E7%9A%84%E6%AD%B7%E5%8F%B2%E8%A8%98%E9%8C%84)\n    - [我想找到引用特定提交的標籤](#%E6%88%91%E6%83%B3%E6%89%BE%E5%88%B0%E5%BC%95%E7%94%A8%E7%89%B9%E5%AE%9A%E6%8F%90%E4%BA%A4%E7%9A%84%E6%A8%99%E7%B1%A4)\n  - [子模組](#%E5%AD%90%E6%A8%A1%E7%B5%84)\n    - [複製所有子模組](#%E8%A4%87%E8%A3%BD%E6%89%80%E6%9C%89%E5%AD%90%E6%A8%A1%E7%B5%84)\n    - [移除子模組](#%E7%A7%BB%E9%99%A4%E5%AD%90%E6%A8%A1%E7%B5%84)\n  - [雜項](#%E9%9B%9C%E9%A0%85)\n    - [從另一個分支拷貝檔案](#%E5%BE%9E%E5%8F%A6%E4%B8%80%E5%80%8B%E5%88%86%E6%94%AF%E6%8B%B7%E8%B2%9D%E6%AA%94%E6%A1%88)\n    - [恢復刪除的檔案](#%E6%81%A2%E5%BE%A9%E5%88%AA%E9%99%A4%E7%9A%84%E6%AA%94%E6%A1%88)\n    - [刪除標籤](#%E5%88%AA%E9%99%A4%E6%A8%99%E7%B1%A4)\n    - [恢復已刪除標籤](#%E6%81%A2%E5%BE%A9%E5%B7%B2%E5%88%AA%E9%99%A4%E6%A8%99%E7%B1%A4)\n    - [已刪除修補檔](#%E5%B7%B2%E5%88%AA%E9%99%A4%E4%BF%AE%E8%A3%9C%E6%AA%94)\n    - [將版本庫導出為 Zip 檔](#%E5%B0%87%E7%89%88%E6%9C%AC%E5%BA%AB%E5%B0%8E%E5%87%BA%E7%82%BA-zip-%E6%AA%94)\n    - [推送有相同名稱的分支與標籤](#%E6%8E%A8%E9%80%81%E6%9C%89%E7%9B%B8%E5%90%8C%E5%90%8D%E7%A8%B1%E7%9A%84%E5%88%86%E6%94%AF%E8%88%87%E6%A8%99%E7%B1%A4)\n  - [追蹤檔案](#%E8%BF%BD%E8%B9%A4%E6%AA%94%E6%A1%88)\n    - [我只想改變一個檔案名稱的大小寫，而不修改內容](#%E6%88%91%E5%8F%AA%E6%83%B3%E6%94%B9%E8%AE%8A%E4%B8%80%E5%80%8B%E6%AA%94%E6%A1%88%E5%90%8D%E7%A8%B1%E7%9A%84%E5%A4%A7%E5%B0%8F%E5%AF%AB%E8%80%8C%E4%B8%8D%E4%BF%AE%E6%94%B9%E5%85%A7%E5%AE%B9)\n    - [我想在拉取時覆蓋本機檔案](#%E6%88%91%E6%83%B3%E5%9C%A8%E6%8B%89%E5%8F%96%E6%99%82%E8%A6%86%E8%93%8B%E6%9C%AC%E6%A9%9F%E6%AA%94%E6%A1%88)\n    - [我想將檔案從 Git 移除，但保留檔案](#%E6%88%91%E6%83%B3%E5%B0%87%E6%AA%94%E6%A1%88%E5%BE%9E-git-%E7%A7%BB%E9%99%A4%E4%BD%86%E4%BF%9D%E7%95%99%E6%AA%94%E6%A1%88)\n    - [我想將特定檔案還原至某個修訂版](#%E6%88%91%E6%83%B3%E5%B0%87%E7%89%B9%E5%AE%9A%E6%AA%94%E6%A1%88%E9%82%84%E5%8E%9F%E8%87%B3%E6%9F%90%E5%80%8B%E4%BF%AE%E8%A8%82%E7%89%88)\n    - [我想列出提交或分支之間特定檔案的差異](#%E6%88%91%E6%83%B3%E5%88%97%E5%87%BA%E6%8F%90%E4%BA%A4%E6%88%96%E5%88%86%E6%94%AF%E4%B9%8B%E9%96%93%E7%89%B9%E5%AE%9A%E6%AA%94%E6%A1%88%E7%9A%84%E5%B7%AE%E7%95%B0)\n    - [我想 Git 忽略特定檔案的更動](#%E6%88%91%E6%83%B3-git-%E5%BF%BD%E7%95%A5%E7%89%B9%E5%AE%9A%E6%AA%94%E6%A1%88%E7%9A%84%E6%9B%B4%E5%8B%95)\n  - [用 Git 除錯](#%E7%94%A8-git-%E9%99%A4%E9%8C%AF)\n  - [組態](#%E7%B5%84%E6%85%8B)\n    - [我想為 Git 命令設定別名](#%E6%88%91%E6%83%B3%E7%82%BA-git-%E5%91%BD%E4%BB%A4%E8%A8%AD%E5%AE%9A%E5%88%A5%E5%90%8D)\n    - [我想將空目錄加入到版本庫](#%E6%88%91%E6%83%B3%E5%B0%87%E7%A9%BA%E7%9B%AE%E9%8C%84%E5%8A%A0%E5%85%A5%E5%88%B0%E7%89%88%E6%9C%AC%E5%BA%AB)\n    - [我想快取一個版本庫的使用者名稱和密碼](#%E6%88%91%E6%83%B3%E5%BF%AB%E5%8F%96%E4%B8%80%E5%80%8B%E7%89%88%E6%9C%AC%E5%BA%AB%E7%9A%84%E4%BD%BF%E7%94%A8%E8%80%85%E5%90%8D%E7%A8%B1%E5%92%8C%E5%AF%86%E7%A2%BC)\n    - [我想 Git 忽略權限與檔案模式更動](#%E6%88%91%E6%83%B3-git-%E5%BF%BD%E7%95%A5%E6%AC%8A%E9%99%90%E8%88%87%E6%AA%94%E6%A1%88%E6%A8%A1%E5%BC%8F%E6%9B%B4%E5%8B%95)\n    - [我想設定全域使用者資訊](#%E6%88%91%E6%83%B3%E8%A8%AD%E5%AE%9A%E5%85%A8%E5%9F%9F%E4%BD%BF%E7%94%A8%E8%80%85%E8%B3%87%E8%A8%8A)\n  - [我不知道我做錯了什麼](#%E6%88%91%E4%B8%8D%E7%9F%A5%E9%81%93%E6%88%91%E5%81%9A%E9%8C%AF%E4%BA%86%E4%BB%80%E9%BA%BC)\n  - [Git 快捷命令](#git-%E5%BF%AB%E6%8D%B7%E5%91%BD%E4%BB%A4)\n    - [Git Bash](#git-bash)\n    - [Windows 上的 PowerShell](#windows-%E4%B8%8A%E7%9A%84-powershell)\n- [其他資源](#%E5%85%B6%E4%BB%96%E8%B3%87%E6%BA%90)\n  - [書籍](#%E6%9B%B8%E7%B1%8D)\n  - [教學](#%E6%95%99%E5%AD%B8)\n  - [腳本和工具](#%E8%85%B3%E6%9C%AC%E5%92%8C%E5%B7%A5%E5%85%B7)\n  - [GUI 客戶端](#gui-%E5%AE%A2%E6%88%B6%E7%AB%AF)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n## 版本庫\n\n### 我想建立本機版本庫\n\n將現有目錄初始化為 Git 版本庫：\n\n```sh\n(my-folder)$ git init\n```\n\n### 我想複製遠端版本庫\n\n要複製遠端版本庫，找到該版本庫的 URL，然後執行：\n\n```sh\n$ git clone [URL]\n```\n\n版本庫會複製到與其名稱相同的目錄中。確保你能連線到你要從之複製的遠端伺服器（通常來說，這表示你要連接上網際網路。）\n\n如果想要將版本庫複製到不同名稱的目錄：\n\n```sh\n$ git clone [URL] [目錄名稱]\n```\n\n### 我設定了錯的遠端版本庫\n\n有幾種可能的情況：\n\n如果你複製錯了遠端版本庫，刪掉 `git clone` 創建的目錄，然後複製正確的版本庫就好。\n\n如果你為本機版本庫設定了錯的遠端，你可以用以下命令變更 `origin` 的 URL：\n\n```sh\n$ git remote set-url origin [正確的 URL]\n```\n\n詳見 [此 Stack Overflow 討論串](https://stackoverflow.com/questions/2432764/how-to-change-the-uri-url-for-a-remote-git-repository#2432799)。\n\n### 我想將程式碼加到其他人的版本庫中\n\nGit 不允許沒有存取權的人將程式碼加到其他人的版本庫。GitHub，一個 Git 版本庫的託管服務，也不行。不過你可以建議程式碼，透過修補，或者用 GitHub 的分叉與拉取請求。\n\n關於分叉：分叉是版本庫的複本。這不是 Git 的功能，但是是 GitHub、Bitbucket、GitLab——或其他任何託管 Git 版本庫的地方——上很常見的動作。你可以透過其 UI 分叉版本庫。\n\n#### 透過拉取請求建議程式碼\n\n在分叉版本庫後，你只需要一般地將其複製到你的機器上。你可以在 GitHub 上做一些小修改，而不需要複製，但這不是一份 GitHub 飛行規則，所以我們還是來談談該怎麼在本機上操作吧。\n\n```sh\n# 如果你用 SSH 的話：\n$ git clone git@github.com:k88hudson/git-flight-rules.git\n\n# 如果你用 HTTPS 的話：\n$ git clone https://github.com/k88hudson/git-flight-rules.git\n```\n\n如果你 `cd` 進創建的目錄，然後輸入 `git remote`，你會看到遠端的列表。基本上，會有一個遠端——`origin`——指向 `k88hudson/git-flight-rules`。在這個情況下，我們也希望有一個指向你的分叉的遠端。\n\n首先，按照 Git 的慣例，我們用 `origin` 表示你的分叉、`upstream` 表示原本的版本庫。因此，先將 `origin` 重新命名為 `upstream`：\n\n```sh\n$ git remote rename origin upstream\n```\n\n你也可以用 `git remote set-url` 來達到同樣的結果，但會花費更多步驟。\n\n接著，設定一個新的遠端指向你的版本庫：\n\n```sh\n$ git remote add origin git@github.com:YourName/git-flight-rules.git\n```\n\n現在有兩個遠端了：\n\n- `origin` 指向你分叉版本庫。\n- `upstream` 則指向原版版本庫。\n\n`origin` 可以讀寫，`upstream` 則是唯讀的。\n\n當你完成更動後，推送你（通常在某個分支上的）更動到遠端 `origin`。如果是在分支上，你可以用 `--set-upstream` 來避免每次推送都要指定遠端分支。例如：\n\n```sh\n(feature/my-feature)$ git push --set-upstream origin feature/my-feature\n```\n\n你沒辦法用 Git 在 CLI 中發起拉取請求（但有一些工具可以幫你做這件事，例如 [hub](https://github.com/github/hub)）。所以當你準備好時，到 GitHub（或其他 Git 託管服務）上創建拉取請求。\n\n之後也別忘了回覆程式碼的檢閱回饋。\n\n#### 透過修補建議程式碼\n\n另一個建議更動的方法是用 `git format-patch`，這不依賴於如 GitHub 的第三方服務。\n\n`format-patch` 會為你的提交創建一個 `.patch` 檔案，本質上就是類似於能在 GitHub 上看到的提交差異的更動列表。\n\n`git am` 可以用於查看、甚至編輯、套用修補檔。\n\n例如，要基於前一個提交創建修補檔，你可以執行 `git format-patch HEAD^`，來創建一個名字類似於 `0001-提交訊息.patch` 的修補檔。\n\n將修補檔套用至你的版本庫則需執行 `git am ./0001-提交訊息.patch`。\n\n修補檔也可以以 `git send-email` 命令透過 email 傳送。使用與組態資訊參見：https://git-send-email.io\n\n#### 我需要將分叉更新到原版的最新進度\n\n在一段時間後，`upstream` 版本庫可能更新了，而這些更新需要拉取至你的 `origin` 版本庫。\n\n你可能已經設定了指向原版的遠端。如果還沒的話，執行以下命令。通常我們用 `upstream` 作為名稱：\n\n```sh\n$ git remote add upstream [原版的 URL]\n```\n\n現在你可以從 `upstream` 抓取，並取得最新更新了。\n\n```sh\n(main)$ git fetch upstream\n(main)$ git merge upstream/main\n\n# 或者：\n(main)$ git pull upstream main\n```\n\n## 編輯提交\n\n### 我剛才提交了什麼？\n\n如果你盲目地用 `git commit -a` 提交了更動，而不確定到底提交了哪些內容，可以用以下命令顯示目前 `HEAD` 上的最近一次的提交：\n\n```sh\n(main)$ git show\n```\n\n或者\n\n```sh\n$ git log -n1 -p\n```\n\n如果你想查看特定提交的特定檔案，你可以用：（`[提交]` 是你想要的提交）\n\n```sh\n$ git show [提交]:filename\n```\n\n### 我的提交訊息寫錯了\n\n如果你的提交訊息寫錯了，且這次提交還沒有推送，可以透過下面的方法來修改提交訊息：\n\n```sh\n$ git commit --amend --only\n```\n\n這會開啟你的預設編輯器來編輯訊息。你也可以選擇只靠一個命令來做這些事：\n\n```sh\n$ git commit --amend --only -m 'xxxxxxx'\n```\n\n如果你已經推送了提交，可以在修改後強制推送，但是不推薦這麼做。\n\n### 我提交裡的使用者名稱和信箱不對\n\n如果只是單個提交有錯，修正它：\n\n```sh\n$ git commit --amend --no-edit --author \"New Authorname <authoremail@mydomain.com>\"\n```\n\n另一個方法是在 `git config --global author.(name|email)` 正確配置你的作者資訊，然後用：\n\n```sh\n$ git commit --amend --no-edit --reset-author\n```\n\n如果你需要修改所有歷史記錄，參考 `git filter-branch` 的手冊頁。\n\n### 我想從一個提交裡移除一個檔案\n\n要從一個提交裡移除一個檔案：\n\n```sh\n$ git checkout HEAD^ filename\n$ git add filename\n$ git commit --amend --no-edit\n```\n\n如果該檔案是新加入的，而你想要（從 Git）刪除它，用：\n\n```sh\n$ git rm --cached filename\n$ git commit --amend --no-edit\n```\n\n當你有一個開放的修補，而你往上面提交了一個不必要的檔案，需要強制推送去更新這個遠端修補時，這非常有用。`--no-edit` 選項將保留現有提交訊息。\n\n### 我想將更動從一個提交移到另一個\n\n如果你在一個提交作了一個更動，而它更符合另一個提交做的事，你可以用互動式重定基底將更動移動過去。這節來自 [Stack Overflow](https://stackoverflow.com/a/54985304/2491502)。\n\n假設你有三個提交，`a`、`b`、`c`。`b` 變更了 `file1` 和 `file2`，你想要把 `file1` 的更動從 `b` 移到 `a`。\n\n首先，互動式重定基底：\n\n```sh\n$ git rebase -i HEAD~3\n```\n\n這會打開包含以下內容的編輯器：\n\n```vim\npick a\npick b\npick c\n```\n\n將 `a` 和 `b` 那行改為 `edit`：\n\n```vim\nedit a\nedit b\npick c\n```\n\n儲存並關閉編輯器後，你會被帶到 `b`。重設 `file1` 的更動：\n\n```sh\n$ git reset HEAD~1 file1\n```\n\n這會取消暫存 `file1` 的更動。貯存更動然後繼續重定基底：\n\n```sh\n$ git stash\n$ git rebase --continue\n```\n\n現在要編輯 `a`。彈出貯存，將更動加入這個提交，然後繼續重定基底：\n\n```sh\n$ git stash pop\n$ git add file1\n$ git commit --amend --no-edit\n$ git rebase --continue\n```\n\n現在你完成重定基底，並將更動從 `b` 移到 `a` 了。如果你要將更動從 `b` 移到 `c`，因為 `c` 在 `b` 之前，你會需要重定基底兩次，一次將更動從 `b` 取出，一次將更動加入到 `c`。\n\n### 我想刪除我最後一次提交\n\n如果你需要刪除推送了的提交，你可以使用以下方法。但是，這將不可逆的改變你的歷史記錄，也會搞亂那些已經從該版本庫拉取了的人的歷史記錄。簡而言之，如果你不是很確定，千萬不要這麼做。\n\n```sh\n$ git reset HEAD^ --hard\n$ git push --force-with-lease [遠端] [分支]\n```\n\n如果你還沒有推送到遠端，重設到你最後一次提交前的狀態就可以了（同時保存暫存的更動）：\n\n```\n(my-branch)$ git reset --soft HEAD^\n```\n\n這只能在推送之前使用。如果你已經推送了，唯一安全的做法是 `git revert [不要的提交]`，那會創建一個新的提交來還原前一個提交的所有更動；或者，如果這個分支是重定基底安全的（即其他開發者不會從這個分支拉取），只需要使用 `git push --force-with-lease`，參見這一節前半部分。\n\n### 刪除任意提交\n\n同樣，除非必須，否則不要這麼做。\n\n```sh\n$ git rebase --onto [不要的提交]^ [不要的提交]\n$ git push --force-with-lease [遠端] [分支]\n```\n\n或者使用[互動式重定基底](#%E6%88%91%E9%9C%80%E8%A6%81%E7%B5%84%E5%90%88%E5%B9%BE%E5%80%8B%E6%8F%90%E4%BA%A4)刪除那些你想要刪除的提交所對應的行。\n\n### 我嘗試推送一個修正後的提交到遠端，但是報錯\n\n```sh\nTo https://github.com/yourusername/repo.git\n! [rejected]        mybranch -> mybranch (non-fast-forward)\nerror: failed to push some refs to 'https://github.com/tanay1337/webmaker.org.git'\nhint: Updates were rejected because the tip of your current branch is behind\nhint: its remote counterpart. Integrate the remote changes (e.g.\nhint: 'git pull ...') before pushing again.\nhint: See the 'Note about fast-forwards' in 'git push --help' for details.\n```\n\n注意，重定基底和修正會**用新的提交取代舊的**，所以如果舊的提交已經推送到遠端上了，那你必須強制推送。注意：總是確保你指明一個分支！\n\n```sh\n(my-branch)$ git push --force-with-lease origin mybranch\n```\n\n一般來說，**應該避免強制推送**。最好是創建和推送一個新的提交，而不是強制推送一個修正後的提交。後者會使其他開發者該分支或其子分支的歷史記錄，與遠端歷史記錄產生衝突。`--force-with-lease` 仍然可能失敗，如果有人在同樣的分支上推送了提交，而你的推送會覆蓋他們的更動。\n\n如果你*完全*確定沒有人在同一個分支上工作，或者你想要*無條件*更新分支的頂端，你可以用 `--force`（`-f`），但通常應該避免。\n\n### 我意外地硬性重設了，我想找回我的內容\n\n如果你意外地做了 `git reset --hard`，你通常能找回你的提交，因為 Git 對每件事都會有日誌，且都會保存幾天。\n\n注意，只適用於你的作業備份了的情況，即有提交或貯存。`git reset --hard` *會移除*未提交的更動，所以請謹慎使用。（更安全的選擇是 `git reset --keep`。）\n\n```sh\n(main)$ git reflog\n```\n\n你將會看到一個你過去提交的列表，和一個重設的提交。選擇你想要回到的提交的 SHA，再重設一次：\n\n```sh\n(main)$ git reset --hard [SHA]\n```\n\n### 我意外地提交並推送了合併\n\n如果你意外地將功能分支在準備好合併之前，合併進了主開發分支，你可以撤銷合併。但有個問題：合併提交有多於一個親代（通常是兩個）。\n\n使用命令：\n\n```sh\n(feature-branch)$ git revert -m 1 [提交]\n```\n\n`-m 1` 選項的意思是選擇 1 號親代（合併進去的分支）作為要還原到的親代。\n\n注意，親代編號不是提交識別符。合併提交有一行 `Merge: 8e2ce2d 86ac2e7`，親代編號是這行上的親代從 1 開始的索引，第一個識別符是 1 號親代，第二個是 2 號，以此類推。\n\n### 我意外地提交並推送了敏感資料\n\n如果你意外地推送了包含敏感或私人資料（密碼、金鑰等）的檔案，你可以修正該提交。記得，你應該認定其中的所有資料都外洩了。以下步驟可以從你的本機複本和公開版本庫移除敏感資料，但你**不能**從別人拉取的複本移除敏感資料。如果你提交了密碼，**立刻變更**，如果你提交了金鑰，**立刻重新生成**。修正推送的提交並不夠，任何人都可能拉取了包含敏感資料的原提交。\n\n如果你編輯檔案移除了敏感資料，執行：\n\n```sh\n$ git add [編輯過的檔案]\n$ git commit --amend --no-edit\n$ git push --force-with-lease [遠端] [分支]\n```\n\n或是將敏感資料儲存在本機環境變數。\n\n如果你希望移除整個檔案（但保留在本機），執行：\n\n```sh\n$ git rm --cached [敏感的檔案]\n$ echo [敏感的檔案] >> .gitignore\n$ git add .gitignore\n$ git commit --amend --no-edit\n$ git push --force-with-lease [遠端] [分支]\n```\n\n如果你同時做了其他提交（即，敏感資料不是在上一個提交引入的），你需要重定基底。\n\n### 我想要從現有的版本庫歷史記錄中移除大檔案\n\n如果你想移除的檔案是機密或敏感的，見[〈我意外地提交並推送了敏感資料〉](#%E6%88%91%E6%84%8F%E5%A4%96%E5%9C%B0%E6%8F%90%E4%BA%A4%E4%B8%A6%E6%8E%A8%E9%80%81%E4%BA%86%E6%95%8F%E6%84%9F%E8%B3%87%E6%96%99)。\n\n即使你在最近的提交中刪除了大或不想要的檔案，它仍然存於 Git 歷史記錄，存於版本庫的 `.git` 目錄中，且 `git clone` 也會下載到不需要的檔案。\n\n這節中提到的操作需要強制推送，且會重寫版本庫大部分的歷史，所以如果你與其他人在進行遠端協作，請先確認他們的本機複本都推送了。\n\n有兩個方法可以重寫歷史記錄：內建的 `git filter-branch` 或 [BFG Repo-Cleaner](https://rtyley.github.io/bfg-repo-cleaner/)。BFG 能以更好的效能顯著清理，但是是第三方，且需要 Java。這裡兩種選擇都會描述。最後一步是強制推送，這需要比起一般強制推送更再三考慮，因為這會永久變更版本庫大量的歷史記錄。\n\n#### 推薦的工具：第三方的 BFG\n\nBFG Repo Cleaner 需要 Java。到[這裡]下載 BFG 的 JAR 檔。以下例子中將假設檔案名稱為 `bfg.jar`，位於 `~/Downloads/`。\n\n刪除特定檔案：\n\n```sh\n$ git rm path/filename\n$ git commit\n$ java -jar ~/Downloads/bfg.jar --delete-files filename\n```\n\n注意，你應該直接給 BFG 檔案名稱，即使其在子目錄中。\n\n你也可以用 glob 模式刪除檔案：\n\n```sh\n$ git rm *.jpg\n$ git commit\n$ java -jar ~/Downloads/bfg.jar --delete-files *.jpg\n```\n\nBFG 不會影響在最新提交中存在的檔案。例如，版本庫中有幾個大 `.tga` 檔，在之前的提交移除了其中一些，在最新的提交還存在的檔案則不會觸及。\n\n注意，如果你重新命名了檔案，例如原本是 `LargeFileFirstName.mp4` 的檔案在一次提交中重新命名為 `LargeFileSecondName.mp4`，`java -jar ~/Downloads/bfg.jar --delete-files LargeFileSecondName.mp4` 並不會從 Git 歷史記錄中刪除這個檔案。需要對兩個檔案名都執行一次，或使用匹配到兩個檔案名的模式。\n\n#### 內建的工具：`git filter-branch`\n\n`git filter-branch` 較為麻煩且功能較少，但如果你不能安裝或執行 BFG，你可以使用它。\n\n將以下例子中的 `filepattern` 替換為某個檔案名稱或模式，例如 `*.jpg`。所有分支的歷史記錄中匹配到的檔案都會被移除。\n\n```sh\n$ git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch filepattern' --prune-empty --tag-name-filter cat -- --all\n```\n\n解釋：\n\n`--tag-name-filter cat` 是使用 `cat` 命令將原本的標籤套用至新提交上，麻煩、但最簡單的方法。\n\n`--prune-empty` 移除任何變為空的提交。\n\n#### 最後一步：推送你變更過的歷史\n\n一旦你移除了檔案，細心地測試一下你沒有弄壞版本庫的任何東西——如果有，最簡單的方法是重新複製一個，然後重頭來過。最後，可以用 Git 垃圾收集來最小化你本機 `.git` 目錄的大小，然後強制推送。\n\n```sh\n$ git reflog expire --expire=now --all && git gc --prune=now --aggressive\n$ git push --force --tags [遠端]\n```\n\n由於你重寫了整個歷史記錄，`git push` 可能會需要推送太多資料，導致回傳錯誤 `The remote end hung up unexpectedly`（遠端意外掛斷了）。如果出現這個問題，可以嘗試增加 Git post 緩衝區大小：\n\n```sh\n$ git config http.postBuffer 524288000\n$ git push --force\n```\n\n如果沒有用的話，你需要手動將提交分成多塊推送歷史記錄。試著增加以下命令中的 `<數量>` 直到成功推送：\n\n```sh\n(main)$ git push -u [遠端] HEAD~<數量>:refs/head/main --force\n```\n\n第一次成功推送後，逐步減少 `<數量>`，直到可以成功使用常規的 `git push`。\n\n### 我需要變更非最新者的提交的內容\n\n如果你創建了好幾個提交，然後發現自己少做了一些應該在其中的第一個提交做的事。若創建新提交來放這些少做的更動，你會有乾淨的版本庫，但是你的提交便不是「原子」的（也就是說，應該在一起的更動沒有在同一個提交）。因此，你可能會想變更第一個提交，也就是這些更動應該在的地方，並保持其後的提交不變。這種情況下，重定基底或許能幫上忙。\n\n假設你要變更第三新的提交。\n\n```sh\n$ git rebase -i HEAD~4\n```\n\n開始互動式重定基底後，你可以編輯最新的三個提交。啟動的文字編輯器會顯示類似這樣的內容：\n\n```vim\npick 9e1d264 第三新的提交\npick 4b6e19a 第二新的提交\npick f4037ec 最新的提交\n```\n\n將其改為：\n\n```vim\nedit 9e1d264 第三新的提交\npick 4b6e19a 第二新的提交\npick f4037ec 最新的提交\n```\n\n然後儲存並退出編輯器。這表示你想要編輯第三新的提交，並保持其他兩者不變。重定基底會在你想編輯的提交停下，你可以做原本少了的更動，和往常一樣編輯、暫存，然後：\n\n```sh\n$ git commit --amend\n```\n\n這會修正這個提交，也就是用原本的更動和新做出的更動，重新創建一個提交來替換掉舊的。接著繼續重定基底就好了：\n\n```sh\n$ git rebase --continue\n```\n\n## 暫存\n\n### 我想暫存所有追蹤的檔案\n\n```sh\n$ git add -u\n```\n\n#### 只暫存一部分追蹤的檔案\n\n```sh\n$ git add -u *.txt # 只暫存副檔名 .txt 的檔案。\n$ git add -u src/ # 只暫存目錄 src/ 中的檔案。\n```\n\n### 我需要把暫存的內容添加到上一次的提交\n\n```sh\n(my-branch*)$ git commit --amend\n```\n\n如果你沒有要修改提交訊息，可以讓 Git 重用訊息：\n\n```sh\n(my-branch*)$ git commit --amend -C HEAD\n```\n\n### 我想要暫存一個新檔案的一部分，而不是這個檔案的全部\n\n一般來說，如果你想暫存一個檔案的一部分，你可以使用以下命令來開啟互動式介面，並使用 `s` 選項來選擇想要的行。\n\n```sh\n$ git add --patch filename.x # 或 `-p`。\n```\n\n然而，當這個檔案是新的，則需改用以下命令：\n\n```sh\n$ git add -N filename.x\n```\n\n然後，你需要用 `e` 選項來選擇需要添加的行。執行 `git diff --cached` 將會顯示哪些行暫存了、哪些行只儲存在本機。\n\n### 我想把在一個檔案裡的更動加到兩個提交裡\n\n`git add` 會把整個檔案加入到一個提交，`git add -p` 則允許你互動式地選擇想要提交的部分。\n\n### 我暫存了太多更動，而想把它們分到多個提交中\n\n`git reset -p` 會打開修補模式重設對話框。類似於 `git add -p`，但選擇 `yes` 會取消暫存更動。\n\n### 我想把暫存的內容變成未暫存，把未暫存的內容暫存起來\n\n多數情況下，你應該將所有的內容變為未暫存，然後再加入你想要的內容提交。但如果你就是想這麼做，你可以創建一個臨時的提交來儲存你已暫存的內容，然後加入未暫存的內容並貯存起來。最後，重設最後一個提交將原本暫存的內容變為未暫存，最後彈出貯存。\n\n```sh\n$ git commit -m \"WIP\"     # 將之前已暫存的內容提交。\n$ git add .               # 加入未暫存的內容。\n$ git stash               # 貯存剛剛加入的內容。\n$ git reset HEAD^         # 重設到父提交。\n$ git stash pop --index 0 # 彈出貯存。\n```\n\n註一：這裡使用 `pop` 僅僅是因為想盡可能保持冪等。\n\n註二：假如不加上 `--index`，會把暫存的檔案標記為未暫存。[這裡](https://stackoverflow.com/questions/31595873/git-stash-with-staged-files-does-stash-convert-staged-files-to-unstaged?answertab=active#tab-top)解釋得比較清楚。（其大意是說，這是一個較為底層的問題，貯存時會創建兩個提交，一個記錄索引狀態、暫存的內容等，另一個紀錄工作區和其他的一些東西，如果你不在套用時指定索引，Git 會把兩個一起銷毀，所以暫存區裡就空了）。\n\n## 未暫存的更動\n\n### 我想把未暫存的更動移動到新分支\n\n```sh\n$ git checkout -b my-branch\n```\n\n### 我想把未暫存的更動移動到另一個現有分支\n\n```sh\n$ git stash\n$ git checkout my-branch\n$ git stash pop\n```\n\n### 我想捨棄未提交的更動\n\n取消暫存所有更動：\n\n```sh\n$ git reset\n```\n\n捨棄所有未提交的更動（在版本庫根目錄執行）：\n\n```sh\n$ git checkout .\n```\n\n捨棄特定檔案未提交的更動：\n\n```sh\n$ git checkout [檔案名稱]\n```\n\n另一個捨棄所有未提交的更動的方法（比較長，但可以在任何子目錄執行）：\n\n```sh\n$ git reset --hard HEAD\n```\n\n移除所有未追蹤的本機檔案，只有 Git 追蹤的會保留：\n\n```sh\n$ git clean -fd\n```\n\n`-x` 能將忽略的檔案也移除。\n\n### 我想捨棄某些未暫存的更動\n\n如果只想捨棄某些更動，而不是全部，簽出不要的、保留要的：\n\n```sh\n$ git checkout -p\n# 回答 y 捨棄不要的更動。\n```\n\n另外一個方法是使用貯存。貯存所有要的更動，重設工作複本，然後把貯存彈出。\n\n```sh\n$ git stash -p\n# Select all of the snippets you want to save\n$ git reset --hard\n$ git stash pop\n```\n\n或者，貯存你不需要的部分，然後捨棄貯存。\n\n```sh\n$ git stash -p\n# Select all of the snippets you don't want to save\n$ git stash drop\n```\n\n## 分支\n\n### 我想列出所有分支\n\n列出本機分支：\n\n```sh\n$ git branch\n```\n\n列出遠端分支：\n\n```sh\n$ git branch -r\n```\n\n列出兩者：\n\n```sh\n$ git branch -a\n```\n\n### 我想從一個提交創建分支\n\n```sh\n$ git checkout -b [分支名稱] [提交 SHA]\n```\n\n### 我從錯誤的分支拉取，或拉取到錯誤的分支了\n\n這是另外一種可以使用 `git reflog` 情況。找到在這次錯誤拉取之前 HEAD 的指向。\n\n```sh\n(main)$ git reflog\nab7555f HEAD@{0}: pull origin wrong-branch: Fast-forward\nc5bc55a HEAD@{1}: checkout: checkout message goes here\n```\n\n然後，重設分支到所需的提交：\n\n```sh\n$ git reset --hard c5bc55a\n```\n\n完成。\n\n### 我想捨棄本機上的提交，以讓分支與遠端保持一致\n\n首先，確認你沒有推送到遠端。\n\n`git status` 會顯示本機領先遠端多少個提交：\n\n```sh\n(my-branch)$ git status\n# On branch my-branch\n# Your branch is ahead of 'origin/my-branch' by 2 commits.\n#   (use \"git push\" to publish your local commits)\n#\n```\n\n一種方法是：\n\n```sh\n(my-branch)$ git reset --hard origin/my-branch\n```\n\n### 我需要提交到一個新分支，但錯誤的提交到了 `main`\n\n在 `main` 下創建一個新分支：\n\n```sh\n(main)$ git branch my-branch\n```\n\n把 `main` 重設到前一個提交：\n\n```sh\n(main)$ git reset --hard HEAD^\n```\n\n`HEAD^` 是 `HEAD^1` 的縮寫，表示 `HEAD` 的第一個親代，而 `HEAD^2` 則是其第二個親代（合併提交會有兩個親代）。\n\n請注意 `HEAD^2` **不同於** `HEAD~2`，詳見 [這篇部落格](http://www.paulboxley.com/blog/2011/06/git-caret-and-tilde)。\n\n或者，如果你不想用 `HEAD^`，找到想要將 `main` 重設到的提交的雜湊值（`git log` 可以做到這件事）。然後重設到那個提交。例如，要將 `main` 重設到 `a13b85e`，執行 `git reset --hard a13b85e`。\n\n簽出剛才新建的分支繼續工作：\n\n```sh\n(main)$ git checkout my-branch\n```\n\n### 我想從另一個引用之類保留整個檔案\n\n假設你正在做一個探針解決方案（註），有成百上千的更動，一切都運作良好。現在，你提交到另一個分支來儲存該工作：\n\n```sh\n(solution)$ git add -A && git commit -m \"Adding all changes from this spike into one big commit.\"\n```\n\n當你想要把它放到一個分支裡（可能是功能分支，可能是 `develop`），你希望保持整個檔案的完整，並將大的提交分割成數個小的。\n\n假設有：\n  * 分支 `solution`，擁有原型方案，領先 `develop`。\n  * 分支 `develop`，你想套用解決方案的分支。\n\n假如檔案名稱是 `file1.txt`，你可以將 `solution` 分支的那個檔案的內容放到 `develop` 分支。\n\n```sh\n(develop)$ git checkout solution -- file1.txt\n(develop)$ git status\n# On branch develop\n# Your branch is up-to-date with 'origin/develop'.\n# Changes to be committed:\n#  (use \"git reset HEAD <file>...\" to unstage)\n#\n#        modified:   file1.txt\n```\n\n然後，普通地提交。\n\n註：探針解決方案（spike solution）旨在分析或解決問題。當所有人都清楚瞭解問題後，這些方案將被評估或捨棄。參見 [Wikipedia](https://en.wikipedia.org/wiki/Extreme_programming_practices)。\n\n### 我把在同一分支提交了幾次，而這些提交應該在不同的分支上\n\n假設在 `main` 分支，執行 `git log` 的結果如下：\n\n```sh\n(main)$ git log\n\ncommit e3851e817c451cc36f2e6f3049db528415e3c114\nAuthor: Alex Lee <alexlee@example.com>\nDate:   Tue Jul 22 15:39:27 2014 -0400\n\n    Bug #21 - Added CSRF protection\n\ncommit 5ea51731d150f7ddc4a365437931cd8be3bf3131\nAuthor: Alex Lee <alexlee@example.com>\nDate:   Tue Jul 22 15:39:12 2014 -0400\n\n    Bug #14 - Fixed spacing on title\n\ncommit a13b85e984171c6e2a1729bb061994525f626d14\nAuthor: Aki Rose <akirose@example.com>\nDate:   Tue Jul 21 01:12:48 2014 -0400\n\n    First commit\n```\n\n要將 `e3851e8` 和 `5ea5173` 分別移到新的分支，首先，要把 `main` 分支重設到正確的提交（`a13b85e`）：\n\n```sh\n(main)$ git reset --hard a13b85e\nHEAD is now at a13b85e\n```\n\n新增一個分支：\n\n```sh\n(main)$ git checkout -b 21\n```\n\n接著，將提交揀選到這個分支的頂端。這意味著套用、且只套用該提交，直接在 `HEAD` 的頂端。\n\n```sh\n(21)$ git cherry-pick e3851e8\n```\n\n這可能會造成衝突，參見〈[互動式重定基底可能出現的問題](#%E4%BA%92%E5%8B%95%E5%BC%8F%E9%87%8D%E5%AE%9A%E5%9F%BA%E5%BA%95%E5%8F%AF%E8%83%BD%E5%87%BA%E7%8F%BE%E7%9A%84%E5%95%8F%E9%A1%8C)・[衝突](#%E8%A1%9D%E7%AA%81)〉來解決衝突。\n\n同樣地，為 `5ea5173` 也創建一個分支，並把提交揀選到其上：\n\n```sh\n(main)$ git checkout -b 14\n(14)$ git cherry-pick 5ea5173\n```\n\n### 我想刪除上游刪除了的本機分支\n\n比方說，在 GitHub 中，拉取請求合併後，會有一個選項可以刪除你分叉中合併了的分支。如果你並未計劃在該分支上繼續工作，將該分支的本機複本刪除會更乾淨，而不會有一堆陳舊分支。\n\n```sh\n$ git fetch -p [遠端]\n```\n\n### 我不小心刪除了分支\n\n如果你定期推送到遠端，多數情況下應該是安全的。但有時可能刪除了還沒推送的分支。為了模擬這種情況，首先，創建一個分支和一個檔案：\n\n```sh\n(main)$ git checkout -b my-branch\n(my-branch)$ touch foo.txt\n(my-branch)$ ls\nREADME.md foo.txt\n```\n\n加入更動並提交：\n\n```sh\n(my-branch)$ git add .\n(my-branch)$ git commit -m 'foo.txt added'\n(my-branch)$ git log\n\ncommit 4e3cd85a670ced7cc17a2b5d8d3d809ac88d5012\nAuthor: siemiatj <siemiatj@example.com>\nDate:   Wed Jul 30 00:34:10 2014 +0200\n\n    foo.txt added\n\ncommit 69204cdf0acbab201619d95ad8295928e7f411d5\nAuthor: Kate Hudson <katehudson@example.com>\nDate:   Tue Jul 29 13:14:46 2014 -0400\n\n    Fixes #6: Force pushing after amending commits\n```\n\n現在，切回 `main` 分支，並「不小心」刪除了 `my-branch`：\n\n```sh\n(my-branch)$ git checkout main\nSwitched to branch 'main'\nYour branch is up-to-date with 'origin/main'.\n(main)$ git branch -D my-branch\nDeleted branch my-branch (was 4e3cd85).\n(main)$ echo oh noes, deleted my branch!\noh noes, deleted my branch!\n```\n\n你應該想起了 `reflog`，它記錄了所有動作。\n\n```\n(main)$ git reflog\n69204cd HEAD@{0}: checkout: moving from my-branch to main\n4e3cd85 HEAD@{1}: commit: foo.txt added\n69204cd HEAD@{2}: checkout: moving from main to my-branch\n```\n\n如你所見，其中包含了刪除分支的提交的雜湊值。可以藉此把提交找回來：\n\n```sh\n(main)$ git checkout -b my-branch-help\nSwitched to a new branch 'my-branch-help'\n(my-branch-help)$ git reset --hard 4e3cd85\nHEAD is now at 4e3cd85 foo.txt added\n(my-branch-help)$ ls\nREADME.md foo.txt\n```\n\n看！我們把遺失的檔案找回來了。Git 的 `reflog` 在重定基底出錯時也同樣有用。\n\n### 我想刪除一個分支\n\n刪除一個遠端分支：\n\n```sh\n(main)$ git push origin --delete my-branch\n```\n\n或：\n\n```sh\n(main)$ git push origin :my-branch\n```\n\n刪除一個本機分支：\n\n```sh\n(main)$ git branch -D my-branch\n```\n\n刪除一個*未*合併進目前分支或上游的分支：\n\n```sh\n(main)$ git branch -D my-branch\n```\n\n### 我想刪除多個分支\n\n假如你想刪除以 `fix/` 開頭的所有分支：\n\n```sh\n(main)$ git branch | grep 'fix/' | xargs git branch -d\n```\n\n### 我想重新命名一個分支\n\n重新命名目前的本機分支：\n\n```sh\n$ git branch -m [新名稱]\n```\n\n重新命名另一個本機分支：\n\n```sh\n$ git branch -m [原名稱] [新名稱]\n```\n\n刪除遠端上原名稱的分支，並推送新名稱的分支：\n\n```sh\n$ git push [遠端] :[原名稱] [新名稱]\n```\n\n### 我想簽出別人正在其上工作的遠端分支\n\n首先，從遠端抓取所有分支：\n\n```sh\n(main)$ git fetch --all\n```\n\n假設你想要從遠端 `origin` 簽出分支 `daves`。\n\n```sh\n(main)$ git checkout --track origin/daves\nBranch daves set up to track remote branch daves from origin.\nSwitched to a new branch 'daves'\n```\n\n（`--track` 是 `git checkout -b [分支] [遠端]/[分支]` 的縮寫。）\n\n這樣就有 `daves` 的本機複本了。\n\n### 我想從本機分支創建一個遠端的\n\n```sh\n$ git push [遠端] HEAD\n```\n\n如果你亦希望將該遠端分支設為上游，則改用：\n\n```sh\n$ git push -u [遠端] HEAD\n```\n\n若 `push.default` 組態為 `upstream` 模式或 `simple` 模式（Git 2.0 的預設值），以下命令會將目前分支推送到先前以 `-u` 註冊的遠端分支：\n\n```sh\n$ git push\n```\n\n`git push` 其他模式的行為參見 [`push.default` 的文件](https://git-scm.com/docs/git-config#Documentation/git-config.txt-pushdefault)。\n\n### 我想設定本機分支的上游\n\n設定目前的本機分支的上游：\n\n```sh\n$ git branch --set-upstream-to [遠端]/[分支]\n# 或\n$ git branch -u [遠端]/[分支]\n```\n\n設定另一個本機分支的上游：\n\n```sh\n$ git branch -u [遠端]/[分支] [本機分支]\n```\n\n### 我想設定 `HEAD` 追蹤預設遠端分支\n\n透過檢查遠端分支，可以看到 `HEAD` 在追蹤哪個遠端分支。在某些情況下，可能不會是希望的分支。\n\n```sh\n$ git branch -r\norigin/HEAD -> origin/gh-pages\norigin/main\n```\n\n設定 `origin/HEAD` 追蹤 `origin/main`：\n\n```sh\n$ git remote set-head origin --auto\norigin/HEAD set to main\n```\n\n### 我在錯誤的分支上做了更動\n\n如果你有未提交的更動，而其應該在另一個分支上，貯存更動然後在正確的分支上套用：\n\n```sh\n(wrong-branch)$ git stash\n(wrong-branch)$ git checkout correct-branch\n(correct-branch)$ git stash apply\n```\n\n### 我想將分支一分為二\n\n你在一個分支上提交了幾次，而你想其一分為二，一個結束於較早的某個提交，一個包含所有提交。\n\n用 `git log` 找到你想作為分開點的提交的 SHA，然後：\n\n```sh\n(original-branch)$ git branch new-branch\n(original-branch)$ git reset --hard [分開點]\n```\n\n如果你先前已推送 `original-branch`，你將需要強制推送，參見 [Stack Overflow](https://stackoverflow.com/questions/28983458/how-to-split-a-branch-in-two-with-git/28983843#28983843)。\n\n## 重定基底與合併\n\n### 撤銷重定基底或合併\n\n你可能對一個錯誤的分支做了重定基底或合併，或者無法完成重定基底或合併。Git 在進行危險操作時，會將原本的 `HEAD` 存成 `ORIG_HEAD`，因此可以很容易的恢復到之前的狀態。\n\n```sh\n(my-branch)$ git reset --hard ORIG_HEAD\n```\n\n### 我重定了基底，但我不想強制推送\n\n不幸的是，如果你想把重定基底的結果反映在遠端分支上，你必須強制推送。因為歷史記錄變更了，遠端不會接受使用快轉，而必須強制推送。這就是許多人使用合併工作流程、而不是重定基底工作流程的主要原因之一，強制推送會使大團隊陷入麻煩。\n\n一種安全的方式是，不要推送到遠端：\n\n```sh\n(main)$ git checkout my-branch\n(my-branch)$ git rebase -i main\n(my-branch)$ git checkout main\n(main)$ git merge --ff-only my-branch\n```\n\n參見[此 Stack Overflow 討論串](http://stackoverflow.com/questions/11058312/how-can-i-use-git-rebase-without-requiring-a-forced-push)。\n\n### 我需要組合幾個提交\n\n假設你在（將）對 `main` 分支拉取請求的分支上工作。最簡單的例子中，你只是想將所有的提交組合成一個單獨的提交，且你不關心提交的時間戳，你可以重設和重新提交。確保 `main` 是最新的，且你的更動都提交了，然後：\n\n```sh\n(my-branch)$ git reset --soft main\n(my-branch)$ git commit -am \"New awesome feature\"\n```\n\n如果你想更精細地控制、保留時間戳，你需要互動式重定基底：\n\n```sh\n(my-branch)$ git rebase -i main\n```\n\n如果沒有相對於另一個分支，你將不得不相對於 `HEAD` 重定基底。例如，要壓縮最近的兩次提交，需對 `HEAD~2` 重定基底；組合最近三次提交，則是對 `HEAD~3`；以此類推。\n\n```sh\n(main)$ git rebase -i HEAD~2\n```\n\n在執行了互動式重定基底的命令後，你會在編輯器裡看到類似以下的內容：\n\n```vim\npick a9c8a1d Some refactoring\npick 01b2fd8 New awesome feature\npick b729ad5 fixup\npick e3851e8 another fix\n\n# Rebase 8074d12..b729ad5 onto 8074d12\n#\n# Commands:\n#  p, pick = use commit\n#  r, reword = use commit, but edit the commit message\n#  e, edit = use commit, but stop for amending\n#  s, squash = use commit, but meld into previous commit\n#  f, fixup = like \"squash\", but discard this commit's log message\n#  x, exec = run command (the rest of the line) using shell\n#\n# These lines can be re-ordered; they are executed from top to bottom.\n#\n# If you remove a line here THAT COMMIT WILL BE LOST.\n#\n# However, if you remove everything, the rebase will be aborted.\n#\n# Note that empty commits are commented out\n```\n\n以 `#` 開頭的行是註解，不影響重定基底。\n\n你可以用註解中列出的命令替換 `pick`，也可以刪除一行來刪除對應的提交。\n\n例如，如果要**保留最舊（第一個）的提交，並將其餘的組合成第二個提交**，應該將第二個提交之後所有提交的命令改為 `f`：\n\n```vim\npick a9c8a1d Some refactoring\npick 01b2fd8 New awesome feature\nf b729ad5 fixup\nf e3851e8 another fix\n```\n\n如果要組合**並重新命名這個提交**，應該在第二個提交加上 `r`，或使用 `s` 取代 `f`：\n\n```vim\npick a9c8a1d Some refactoring\npick 01b2fd8 New awesome feature\ns b729ad5 fixup\ns e3851e8 another fix\n```\n\n你可以在接著彈出的編輯器中重新命名那個提交：\n\n```vim\nNewer, awesomer features\n\n# Please enter the commit message for your changes. Lines starting\n# with '#' will be ignored, and an empty message aborts the commit.\n# rebase in progress; onto 8074d12\n# You are currently editing a commit while rebasing branch 'main' on '8074d12'.\n#\n# Changes to be committed:\n#\tmodified:   README.md\n#\n```\n\n應該會看到如下的成功訊息：\n\n```sh\nSuccessfully rebased and updated refs/heads/main.\n```\n\n#### 安全合併的策略\n\n`--no-commit` 選項會合併但不會自動提交，給使用者在提交前檢查和修改的機會。`--no-ff` 會留下功能分支存在過的證據，保持歷史記錄一致。\n\n```sh\n(main)$ git merge --no-ff --no-commit my-branch\n```\n\n#### 我需要將整個分支合併成單一提交\n\n```sh\n(main)$ git merge --squash my-branch\n```\n\n#### 我只想組合未推送的提交\n\n假設在推送到上游前，你有幾個在製的提交，這時候不希望把已推送的提交也組合進來，因為其他人可能已經有提交引用它們了。\n\n```sh\n(main)$ git rebase -i @{u}\n```\n\n這會進行一次互動式重定基底，只會列出還沒推送的提交。對這些提交重新排序或做 `squash`、`fixup` 都是安全的。\n\n#### 我需要中止合併\n\n有時合併會導致某些檔案有問題，這種情況下可以用 `--abort` 選項中止衝突解決，嘗試回復到先前的狀態。\n\n```sh\n$ git merge --abort\n```\n\n此命令在 Git 1.7.4 及以後可用。\n\n### 我需要更新分支的親代提交\n\n假設有分支：\n  * `main`\n  * `feature-1`，從 `main` 分支出來\n  * `feature-2`，從 `feature-1` 延伸出來\n\n如果在 `feature-1` 上提交，`feature-2` 的親代提交便不對了（因為是其的延伸，應該要在 `feature-1` 的頂端）。可以用 `git rebase --onto` 來修正這個問題。\n\n```sh\n(feature-2)$ git rebase --onto feature-1 [feature-2 上第一個不想帶來的提交] feature-2\n```\n\n如果你正在一個尚未合併的功能上編寫新的功能，而前者的漏洞修復需要反映到後者的分支，這會很有用。\n\n### 檢查分支上的所有提交是否都合併了\n\n要檢查一個分支上的所有提交是否都已經合併進了另一個分支，應該在這些分支的 `HEAD`（或任何提交）之間檢查差異：\n\n```sh\n(main)$ git log --graph --left-right --cherry-pick --oneline HEAD...feature/120-on-scroll\n```\n\n這會顯示一個分支有而另一個分支沒有的提交，和分支之間不共享的提交的列表。\n\n另一個方法是：\n\n```sh\n(main)$ git log main ^feature/120-on-scroll --no-merges\n```\n\n### 互動式重定基底可能出現的問題\n\n#### 編輯介面出現「noop」\n\n如果你看到：\n\n```\nnoop\n```\n\n表示重定基底的分支和目前分支在同一個提交，或領先目前分支。你可以嘗試：\n  * 確保 `main` 分支沒有問題\n  * 對 `HEAD~2` 或更早的提交重定基底\n\n#### 衝突\n\n如果不能成功的完成重定基底，你可能必須要解決衝突。\n\n首先用 `git status` 檢查哪些檔案有衝突：\n\n```sh\n(my-branch)$ git status\nOn branch my-branch\nChanges not staged for commit:\n  (use \"git add <file>...\" to update what will be committed)\n  (use \"git checkout -- <file>...\" to discard changes in working directory)\n\n\tmodified:   README.md\n```\n\n在這個例子中，`README.md` 有衝突。打開衝突的檔案會看到類似下面的內容：\n\n```vim\n   <<<<<<< HEAD\n   some code\n   =========\n   some code\n   >>>>>>> new-commit\n```\n\n你必須解決新提交的內容和 `HEAD` 中的內容的衝突。\n\n如果你想要保留其中一個分支的版本，你可以用 `--ours` 和 `--theirs`：\n\n```sh\n$ git checkout --ours README.md\n```\n\n* *合併*時，`--ours` 代表保留本機分支的更動，`--theirs` 則是另一個分支的更動。\n* *重定基底*時，`--theirs` 代表保留本機分支的更動，`--ours` 則是另一個分支的更動。\n\n關於為什麼互換了，參見 [Git 文件的此註記](https://git-scm.com/docs/git-rebase#Documentation/git-rebase.txt---merge)。\n\n有時候衝突非常複雜，你可以使用可視化差異編輯器：\n\n```sh\n(main*)$ git mergetool -t opendiff\n```\n\n解決所有衝突後，加入變更了的檔案，然後用 `git rebase --continue` 繼續重定基底：\n\n```sh\n(my-branch)$ git add README.md\n(my-branch)$ git rebase --continue\n```\n\n如果在解決所有衝突過後，得到了與提交前一樣的結果，可以使用 `git rebase --skip`。\n\n如果想放棄重定基底，回到之前的狀態，可以在任何時候用：\n\n```sh\n(my-branch)$ git rebase --abort\n```\n\n## 貯存\n\n### 貯存所有更動\n\n貯存工作目錄下所有更動：\n\n```sh\n$ git stash\n```\n\n也貯存未追蹤的檔案：\n\n```sh\n$ git stash -u\n```\n\n### 貯存指定檔案\n\n貯存一個檔案：\n\n```sh\n$ git stash push working-directory-path/filename.ext\n```\n\n貯存多個檔案：\n\n```sh\n$ git stash push working-directory-path/filename1.ext working-directory-path/filename2.ext\n```\n\n### 貯存時附加訊息\n\n```sh\n$ git stash save <message>\n```\n\n或\n\n```sh\n$ git stash push -m <message>\n```\n\n如此可以在使用 `stash list` 時看到訊息。\n\n### 套用指定貯存\n\n先列出貯存：\n\n```sh\n$ git stash list\n```\n\n然後，將以下命令的 `n` 替換成貯存在堆疊中的位置（最上方為 `0`），套用指定貯存：\n\n```sh\n$ git stash apply \"stash@{n}\"\n```\n\n除此之外，也可以使用時間標記（假如你能記住的話），如：\n\n```sh\n$ git stash apply \"stash@{2.hours.ago}\"\n```\n\n### 貯存時保留未暫存的內容\n\n你需要先手動創建一個貯存提交，然後使用 `git stash store`。\n\n```sh\n$ git stash create\n$ git stash store -m \"commit-message\" CREATED_SHA1\n```\n\n## 尋找\n\n### 我想找到引入特定字串的提交\n\n```sh\n$ git log -S [要尋找的字串]\n```\n\n常見的選項：\n  * `--source` 顯示引用名稱。\n  * `--all` 尋找每個分支。\n  * `--reverse` 以相反順序印出，即第一個為最早如此變更的提交。\n\n### 我想找到特定作者／提交者的提交\n\n尋找特定作者／提交者的提交：\n\n```sh\n$ git log --author=[名字或 email]\n$ git log --committer=[名字或 email]\n```\n\n注意作者與提交者並不相同，`--author` 是寫下程式碼的人，`--committer` 則是提交程式碼的人。\n\n### 我想找到包含特定檔案的提交\n\n```sh\n$ git log -- [檔案路徑]\n```\n\n也可以在檔案路徑中使用萬用字元，如：\n\n```sh\n$ git log -- **/*.js\n```\n\n使用萬用字元時，以 `--name-status` 列出提交的檔案會有幫助：\n\n```sh\n$ git log --name-status -- **/*.js\n```\n\n### 我想找到特定函式的歷史記錄\n\n```sh\n$ git log -L :[函式名稱]:[檔案路徑]\n```\n\n也可以結合其他 `git log` 選項使用，例如[修訂版範圍](https://git-scm.com/docs/gitrevisions)和[提交限制](https://git-scm.com/docs/git-log/#_commit_limiting)。\n\n### 我想找到引用特定提交的標籤\n\n```sh\n$ git tag --contains [提交]\n```\n\n## 子模組\n\n### 複製所有子模組\n\n```sh\n$ git clone --recursive git://github.com/foo/bar.git\n```\n\n如果已經複製了：\n\n```sh\n$ git submodule update --init --recursive\n```\n\n### 移除子模組\n\n創建子模組很直覺，但刪除不是，你需要：\n\n```sh\n$ git submodule deinit [子模組名稱]\n$ git rm [子模組名稱]\n$ git rm --cached [子模組名稱]\n$ rm -rf .git/modules/[子模組名稱]\n```\n\n## 雜項\n\n### 從另一個分支拷貝檔案\n\n```sh\n$ git checkout [分支] -- [檔案名稱]\n```\n\n### 恢復刪除的檔案\n\n先找到該檔案最後存在的提交：\n\n```sh\n$ git rev-list -n 1 HEAD -- [檔案名稱]\n```\n\n然後簽出該檔案：\n\n```sh\n$ git checkout [刪除檔案的提交]^ -- [檔案名稱]\n```\n\n### 刪除標籤\n\n```sh\n$ git tag -d [標籤名稱]\n$ git push [遠端] :refs/tags/[標籤名稱]\n```\n\n### 恢復已刪除標籤\n\n如果想恢復一個已刪除標籤，首先，找到無法觸及的標籤：\n\n```sh\n$ git fsck --unreachable | grep tag\n```\n\n記下這個標籤的雜湊值，然後用 [`git update-ref`](http://git-scm.com/docs/git-update-ref)：\n\n```sh\n$ git update-ref refs/tags/[標籤名稱] [雜湊值]\n```\n\n### 已刪除修補檔\n\n如果有人在 GitHub 上向你提出了拉取請求，但他接著刪除了他的分叉，因為 [`.diff` 和 `.patch` URL](https://github.com/blog/967-github-secrets) 失效，你無法複製他的提交或使用 `git am`。但你可以透過 [GitHub 的特殊引用](https://gist.github.com/piscisaureus/3342247)簽出拉取請求本身。例如將拉取請求 #1 的內容抓取到名為 `pr_1` 的新分支：\n\n```sh\n$ git fetch [遠端] refs/pull/1/head:pr_1\nFrom github.com:foo/bar\n * [new ref]         refs/pull/1/head -> pr_1\n```\n\n### 將版本庫導出為 Zip 檔\n\n```sh\n$ git archive --format zip --output [zip 的完整檔案路徑] main\n```\n\n### 推送有相同名稱的分支與標籤\n\n如果遠端有與分支同名的標籤，若試圖以標準的 `git push [遠端] [分支]` 命令推送該分支時會得到以下錯誤：\n\n```sh\n$ git push [遠端] [分支]\nerror: dst refspec same matches more than one.\nerror: failed to push some refs to '<git server>'\n```\n\n指明要推送 `HEAD` 引用來修正這個問題：\n\n```sh\n$ git push [遠端] refs/heads/[分支名稱]\n```\n\n相對地，推送標籤使用：\n\n```sh\n$ git push [遠端] refs/tags/[標籤名稱]\n```\n\n## 追蹤檔案\n\n### 我只想改變一個檔案名稱的大小寫，而不修改內容\n\n```sh\n(main)$ git mv --force [原名稱] [新名稱]\n```\n\n### 我想在拉取時覆蓋本機檔案\n\n```sh\n(main)$ git fetch --all\n(main)$ git reset --hard origin/main\n```\n\n### 我想將檔案從 Git 移除，但保留檔案\n\n```sh\n(main)$ git rm --cached [檔案名稱]\n```\n\n### 我想將特定檔案還原至某個修訂版\n\n```sh\n$ git checkout [提交] -- [檔案名稱]\n```\n\n還原多個檔案：\n\n```sh\n$ git checkout [提交] -- [檔案名稱1] [檔案名稱2]\n```\n\n### 我想列出提交或分支之間特定檔案的差異\n\n```sh\n$ git diff [提交1]:[檔案名稱] [提交2]:[檔案名稱]\n# 或\n$ git diff [提交1] [提交2] -- [檔案名稱]\n```\n\n當然，也可以用分支名稱來表示分支頂端的提交。\n\n### 我想 Git 忽略特定檔案的更動\n\n這可以用於不應該提交的組態模板或其他需在本機加入憑證的檔案。\n\n```sh\n$ git update-index --assume-unchanged [要忽略的檔案]\n```\n\n注意，這*並不會*將檔案從版本控制移除——只是在本機上忽略。要取消這個設定，以下命令清除此旗標：\n\n```sh\n$ git update-index --no-assume-unchanged [要取消忽略的檔案]\n```\n\n## 用 Git 除錯\n\n[`git bisect`](https://git-scm.com/docs/git-bisect) 命令透過二分搜尋找到哪個提交引入了漏洞。\n\n假設你在 `main` 分支上，想找到哪個提交導致程式出錯。你開始二分搜尋：\n\n```sh\n$ git bisect start\n```\n\n接著你應該指定哪個提交已經包含了這個漏洞，哪個沒有。例如，你目前所在的修訂版是壞的，而 `v1.1.1` 是好的：\n\n```sh\n$ git bisect bad\n$ git bisect good v1.1.1\n```\n\n接著 Git 會簽出你提供的範圍中間的提交，並詢問該提交是好是壞。你應該會看到類似這樣的訊息：\n\n```sh\nBisecting: 5 revision left to test after this (roughly 5 step)\n[c44abbbee29cb93d8499283101fe7c8d9d97f0fe] Commit message\n(c44abbb)$\n```\n\n然後你可以檢查這個提交是好是壞。然後用以下命令告訴 Git：\n\n```sh\n$ git bisect good # 如果是好的。\n$ git bisect bad  # 如果是壞的。\n```\n\nGit 會從範圍中選擇另一個提交，這個過程將重複直到沒有剩下的修訂版需要檢查，而命令最後會印出**第一個**壞提交。\n\n## 組態\n\n### 我想為 Git 命令設定別名\n\n在 OS X 和 Linux 下，Git 組態檔案位於 `~/.gitconfig`。可以在 `[alias]` 部分設定一些快捷別名（以及容易拼錯的），如：\n\n```vim\n[alias]\n    a = add\n    amend = commit --amend\n    c = commit\n    ca = commit --amend\n    ci = commit -a\n    co = checkout\n    d = diff\n    dc = diff --changed\n    ds = diff --staged\n    f = fetch\n    loll = log --graph --decorate --pretty=oneline --abbrev-commit\n    m = merge\n    one = log --pretty=oneline\n    outstanding = rebase -i @{u}\n    s = status\n    unpushed = log @{u}\n    wc = whatchanged\n    wip = rebase -i @{u}\n    zap = fetch -p\n```\n\n### 我想將空目錄加入到版本庫\n\n你無法這麼做！Git 不支援，但有一個技巧——你可以在該目錄創建包含以下內容的 `.gitignore` 檔案：\n\n```\n# 忽略這個目錄中所有檔案。\n.\n# 除了這個檔案自身。\n!.gitignore\n```\n\n另一個慣例是在該目錄中創建一個名為 `.gitkeep` 的空檔案：\n\n```sh\n$ mkdir 空目錄\n$ touch 空目錄/.gitkeep\n```\n\n你也可以改稱其為 `.keep`，將第二個命令改為 `touch 空目錄/.keep` 即可。\n\n### 我想快取一個版本庫的使用者名稱和密碼\n\n假設有一個版本庫需要身分認證，這時你可以快取使用者名稱和密碼，而不用每次推送和拉取時都輸入一次。憑證協助程式可以做到這點：\n\n```sh\n# 設定 Git 使用憑證記憶快取。\n$ git config --global credential.helper cache\n```\n\n```sh\n# 設定快取在 1 小時後過期（以秒為單位）。\n$ git config --global credential.helper 'cache --timeout=3600'\n```\n\n顯示可能的憑證協助程式：\n\n```sh\n$ git help -a | grep credential\n```\n\n作業系統特定的憑證快取協助程式：\n\n```sh\n# OS X：\n$ git config --global credential.helper osxkeychain\n```\n\n```sh\n# Windows 2.7.3+：\n$ git config --global credential.helper manager\n```\n\n```sh\n# Ubuntu 或其他使用 GNOME 的發行版：\n$ git config --global credential.helper gnome-keyring\n```\n\n其他作業系統和發行版可能有不同的協助程式。\n\n### 我想 Git 忽略權限與檔案模式更動\n\n```sh\n$ git config core.fileMode false\n```\n\n如果要設定為目前登入的使用者的預設行為：\n\n```sh\n$ git config --global core.fileMode false\n```\n\n### 我想設定全域使用者資訊\n\n設定跨版本庫的使用者資訊：\n\n```sh\n$ git config --global user.name [名字]\n$ git config --global user.email [email]\n```\n\n## 我不知道我做錯了什麼\n\n如果你把事情搞砸了：你錯誤地重設、合併、或強制推送後，找不到自己的提交了；抑或你做得很好，但你想回到以前的某個狀態。\n\n這時 `git reflog` 就派上用場了。`reflog` 記錄對分支頂端的任何改變，即使沒有任何分支或標籤參考那個頂端。基本上，只要 `HEAD` 改變，`reflog` 就會記錄下來。然而，這只能用於本機分支，且它只追蹤動作（例如，不會追蹤一個沒被記錄的檔案的任何改變）。\n\n```sh\n(main)$ git reflog\n0a2e358 HEAD@{0}: reset: moving to HEAD~2\n0254ea7 HEAD@{1}: checkout: moving from 2.2 to main\nc10f740 HEAD@{2}: checkout: moving from main to 2.2\n```\n\n上面的 `reflog` 顯示了曾經從 `main` 分支簽出到 `2.2` 分支，然後再簽出回去，還有硬性重設到一個較舊的提交。最新的動作出現在最上面，並以 `HEAD@{0}` 標示。\n\n如果你不小心移回了提交，`reflog` 會包含移回前 `main` 參考的提交（在這個例子中是 `0254ea7`）。只要硬性重設就能恢復到之前的狀態，這提供了歷史記錄不小心被變更時的安全網。\n\n```sh\n$ git reset --hard 0254ea7\n```\n\n摘自[這裡](https://www.atlassian.com/git/tutorials/rewriting-history/git-reflog)。\n\n## Git 快捷命令\n\n### Git Bash\n\n如果你已經很熟悉以上命令的用法了，你可能會想創建一些快捷方式，讓你可以用很短的命令完成複雜的任務。\n\n```sh\nalias sq=squash\n\nfunction squash() {\n    git rebase -i HEAD~$1\n}\n```\n\n將以上命令複製至你的 `.bashrc` 或 `.bash_profile`。\n\n### Windows 上的 PowerShell\n\nWindows 上的 PowerShell 也可以設定別名與函式。將以下命令加到你位於 `$profile` 變數的設定檔，詳見微軟文件網頁的 [關於設定檔](https://learn.microsoft.com/zh-tw/powershell/module/microsoft.powershell.core/about/about_profiles)。\n\n```powershell\nSet-Alias sq Squash-Commit\n\nfunction Squash-Commit {\n    git rebase -i HEAD~$1\n}\n```\n\n# 其他資源\n\n## 書籍\n\n* [Learn Enough Git to Be Dangerous](https://www.learnenough.com/git-tutorial)——Michael Hartl 所著的從基礎開始的 Git 書籍\n* [Pro Git](https://git-scm.com/book/en/v2)——Scott Chacon 與 Ben Straub 合著的傑出書籍\n* [Git Internals](https://github.com/pluralsight/git-internals-pdf)——Scott Chacon 的另一本傑出書籍\n* [Nasa Handbook](https://www.nasa.gov/sites/default/files/atoms/files/nasa_systems_engineering_handbook.pdf)\n\n## 教學\n\n* [19 Git Tips For Everyday Use](https://www.alexkras.com/19-git-tips-for-everyday-use)——實用的 Git 一行命令列表\n* [Atlassian's Git tutorial](https://www.atlassian.com/git/tutorials)——從初學到熟練，正確掌握 Git 的教學\n* [Learn Git branching](https://learngitbranching.js.org/)——分支、合併、重定基底的互動式網頁教學\n* [Getting solid at Git rebase vs. merge](https://medium.com/@porteneuve/getting-solid-at-git-rebase-vs-merge-4fa1a48c53aa)\n* [Git Commands and Best Practices Cheat Sheet](https://zeroturnaround.com/rebellabs/git-commands-and-best-practices-cheat-sheet)——一篇部落格中的 Git 小抄與更多解釋\n* [Git from the inside out](https://codewords.recurse.com/issues/two/git-from-the-inside-out)——深度探討 Git 內部的教學\n* [git-workflow](https://github.com/asmeurer/git-workflow) - [Aaron Meurer](https://github.com/asmeurer)——如何用 Git 貢獻開源版本庫\n* [GitHub as a workflow](https://hugogiraudel.com/2015/08/13/github-as-a-workflow/)——將 GitHub 用作工作流程的有趣做法，尤其是空 PR\n* [Githug](https://github.com/Gazler/githug)——學習常見 Git 工作流程的遊戲\n* [learnGitBranching](https://github.com/pcottle/learnGitBranching)——用於挑戰與教育的互動式 Git 可視化！\n\n## 腳本和工具\n\n* [firstaidgit.io](http://firstaidgit.io/)——一個可搜尋的 Git 常見問題集\n* [git-extra-commands](https://github.com/unixorn/git-extra-commands)——一堆有用的額外 Git 腳本\n* [git-extras](https://github.com/tj/git-extras)——Git 工具集，版本庫概要、repl、歷史記錄、提交百分比和更多\n* [git-fire](https://github.com/qw3rtman/git-fire)——git-fire 是一個 Git 插件，用於在緊急情況下幫助加入目前所有檔案、提交、推送到一個新分支（防止合併衝突）。\n* [git-tips](https://github.com/git-tips/tips)——Git 小撇步\n* [git-town](https://github.com/Originate/git-town)——通用、高級 Git 工作流程支援！<http://www.git-town.com>\n\n## GUI 客戶端\n\n* [GitKraken](https://www.gitkraken.com/)——豪華的 Git 客戶端，適用於 Windows、Mac、Linux\n* [git-cola](https://git-cola.github.io/)——又一個 Git 客戶端，適用於 Windows、OS X\n* [GitUp](https://github.com/git-up/GitUp)——一個新的 Git 客戶端，在解決 Git 的複雜問題上有自己的特點\n* [gitx-dev](https://rowanj.github.io/gitx/)——又一個圖形化的 Git 客戶端，適用於 OS X\n* [Sourcetree](https://www.sourcetreeapp.com/)——簡單而強大的免費 Git GUI 客戶端，適用於 Windows、OS X\n* [Tower](http://www.git-tower.com/)——圖形化 Git 客戶端，適用於 OS X（付費）\n* [tig](https://jonas.github.io/tig/)——Git 的終端文本模式介面\n* [Magit](https://magit.vc/)——Emacs 的 Git 介面\n* [GitExtensions](https://github.com/gitextensions/gitextensions)——殼層插件、Visual Studio 2010-2015 插件、獨立的 Git 版本庫工具\n* [Fork](https://git-fork.com/)——快速且友善的 Git 客戶端，適用於 Mac（beta）\n* [gmaster](https://gmaster.io/)——包含三路合併、分析重構、語意化差異、合併等的 Git 客戶端，適用於 Windows（beta）\n* [gitk](https://git-scm.com/docs/gitk)——可以簡單查看版本庫狀態的 Git 客戶端，適用於 Linux\n* [SublimeMerge](https://www.sublimemerge.com/)——極速、可擴展的客戶端，有三路合併、強大的搜尋、語法高亮功能，活躍開發中\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"private\": true,\n  \"name\": \"git-flight-rules\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Flight rules for git\",\n  \"scripts\": {\n    \"toc\": \"doctoc --github README.md README_*.md\",\n    \"diff\": \"test -z \\\"`git diff -- README.md`\\\" && test -z \\\"`git diff -- README_*.md`\\\"\"\n  },\n  \"devDependencies\": {\n    \"doctoc\": \"^1.3.0\",\n    \"anchor-markdown-header\": \"thlorenz/anchor-markdown-header#master\"\n  }\n}\n"
  }
]