]> git.phdru.name Git - git-wiki.git/blobdiff - pep-103.txt
Rename pep-103.txt -> git-wiki.txt
[git-wiki.git] / pep-103.txt
diff --git a/pep-103.txt b/pep-103.txt
deleted file mode 100644 (file)
index 57ba284..0000000
+++ /dev/null
@@ -1,1047 +0,0 @@
-#format rst
-
-Abstract
-========
-
-This page (it was PEP 103) collects information about git. There is, of
-course, a lot of documentation for git, so the PEP concentrates on
-more complex (and more related to Python development) issues,
-scenarios and examples.
-
-
-Documentation
-=============
-
-Git is accompanied with a lot of documentation, both online and
-offline.
-
-
-Documentation for starters
---------------------------
-
-Git Tutorial: `part 1
-<https://www.kernel.org/pub/software/scm/git/docs/gittutorial.html>`_,
-`part 2
-<https://www.kernel.org/pub/software/scm/git/docs/gittutorial-2.html>`_.
-
-`Git User's manual
-<https://www.kernel.org/pub/software/scm/git/docs/user-manual.html>`_.
-`Everyday GIT With 20 Commands Or So
-<https://www.kernel.org/pub/software/scm/git/docs/giteveryday.html>`_.
-`Git workflows
-<https://www.kernel.org/pub/software/scm/git/docs/gitworkflows.html>`_.
-
-
-Advanced documentation
-----------------------
-
-`Git Magic
-<http://www-cs-students.stanford.edu/~blynn/gitmagic/index.html>`_,
-with a number of translations.
-
-`Pro Git <https://git-scm.com/book>`_. The Book about git. Buy it at
-Amazon or download in PDF, mobi, or ePub form. It has translations to
-many different languages. Download Russian translation from `GArik
-<https://github.com/GArik/progit/wiki>`_.
-
-`Git Wiki <https://git.wiki.kernel.org/index.php/Main_Page>`_.
-
-`Git Buch <http://gitbu.ch/index.html>`_ (German).
-
-
-Offline documentation
----------------------
-
-Git has builtin help: run ``git help $TOPIC``. For example, run
-``git help git`` or ``git help help``.
-
-
-Quick start
-===========
-
-Download and installation
--------------------------
-
-Unix users: `download and install using your package manager
-<https://git-scm.com/download/linux>`_.
-
-Microsoft Windows: download `git-for-windows
-<https://github.com/git-for-windows/git/releases>`_.
-
-MacOS X: use git installed with `XCode
-<https://developer.apple.com/xcode/>`_ or download from `MacPorts
-<https://www.macports.org/ports.php?by=name&substr=git>`_ or
-`git-osx-installer
-<http://sourceforge.net/projects/git-osx-installer/files/>`_ or
-install git with `Homebrew <http://brew.sh/>`_: ``brew install git``.
-
-`git-cola <https://git-cola.github.io/index.html>`_ (`repository
-<https://github.com/git-cola/git-cola>`__) is a Git GUI written in
-Python and GPL licensed. Linux, Windows, MacOS X.
-
-`TortoiseGit <https://tortoisegit.org/>`_ is a Windows Shell Interface
-to Git based on TortoiseSVN; open source.
-
-
-Initial configuration
----------------------
-
-This simple code is often appears in documentation, but it is
-important so let repeat it here. Git stores author and committer
-names/emails in every commit, so configure your real name and
-preferred email::
-
-    $ git config --global user.name "User Name"
-    $ git config --global user.email user.name@example.org
-
-
-Examples in this PEP
-====================
-
-Examples of git commands in this PEP use the following approach. It is
-supposed that you, the user, works with a local repository named
-``python`` that has an upstream remote repo named ``origin``. Your
-local repo has two branches ``v1`` and ``master``. For most examples
-the currently checked out branch is ``master``. That is, it's assumed
-you have done something like that::
-
-    $ git clone https://git.python.org/python.git
-    $ cd python
-    $ git branch v1 origin/v1
-
-The first command clones remote repository into local directory
-`python``, creates a new local branch master, sets
-remotes/origin/master as its upstream remote-tracking branch and
-checks it out into the working directory.
-
-The last command creates a new local branch v1 and sets
-remotes/origin/v1 as its upstream remote-tracking branch.
-
-The same result can be achieved with commands::
-
-    $ git clone -b v1 https://git.python.org/python.git
-    $ cd python
-    $ git checkout --track origin/master
-
-The last command creates a new local branch master, sets
-remotes/origin/master as its upstream remote-tracking branch and
-checks it out into the working directory.
-
-
-Branches and branches
-=====================
-
-Git terminology can be a bit misleading. Take, for example, the term
-"branch". In git it has two meanings. A branch is a directed line of
-commits (possibly with merges). And a branch is a label or a pointer
-assigned to a line of commits. It is important to distinguish when you
-talk about commits and when about their labels. Lines of commits are
-by itself unnamed and are usually only lengthening and merging.
-Labels, on the other hand, can be created, moved, renamed and deleted
-freely.
-
-
-Remote repositories and remote branches
-=======================================
-
-Remote-tracking branches are branches (pointers to commits) in your
-local repository. They are there for git (and for you) to remember
-what branches and commits have been pulled from and pushed to what
-remote repos (you can pull from and push to many remotes).
-Remote-tracking branches live under ``remotes/$REMOTE`` namespaces,
-e.g. ``remotes/origin/master``.
-
-To see the status of remote-tracking branches run::
-
-    $ git branch -rv
-
-To see local and remote-tracking branches (and tags) pointing to
-commits::
-
-    $ git log --decorate
-
-You never do your own development on remote-tracking branches. You
-create a local branch that has a remote branch as upstream and do
-development on that local branch. On push git pushes commits to the
-remote repo and updates remote-tracking branches, on pull git fetches
-commits from the remote repo, updates remote-tracking branches and
-fast-forwards, merges or rebases local branches.
-
-When you do an initial clone like this::
-
-    $ git clone -b v1 https://git.python.org/python.git
-
-git clones remote repository ``https://git.python.org/python.git`` to
-directory ``python``, creates a remote named ``origin``, creates
-remote-tracking branches, creates a local branch ``v1``, configure it
-to track upstream remotes/origin/v1 branch and checks out ``v1`` into
-the working directory.
-
-Some commands, like ``git status --branch`` and ``git branch --verbose``,
-report the difference between local and remote branches.
-Please remember they only do comparison with remote-tracking branches
-in your local repository, and the state of those remote-tracking
-branches can be outdated. To update remote-tracking branches you
-either fetch and merge (or rebase) commits from the remote repository
-or update remote-tracking branches without updating local branches.
-
-
-Updating local and remote-tracking branches
--------------------------------------------
-
-To update remote-tracking branches without updating local branches run
-``git remote update [$REMOTE...]``. For example::
-
-    $ git remote update
-    $ git remote update origin
-
-
-Fetch and pull
-''''''''''''''
-
-There is a major difference between
-
-::
-
-    $ git fetch $REMOTE $BRANCH
-
-and
-
-::
-
-    $ git fetch $REMOTE $BRANCH:$BRANCH
-
-The first command fetches commits from the named $BRANCH in the
-$REMOTE repository that are not in your repository, updates
-remote-tracking branch and leaves the id (the hash) of the head commit
-in file .git/FETCH_HEAD.
-
-The second command fetches commits from the named $BRANCH in the
-$REMOTE repository that are not in your repository and updates both
-the local branch $BRANCH and its upstream remote-tracking branch. But
-it refuses to update branches in case of non-fast-forward. And it
-refuses to update the current branch (currently checked out branch,
-where HEAD is pointing to).
-
-The first command is used internally by ``git pull``.
-
-::
-
-    $ git pull $REMOTE $BRANCH
-
-is equivalent to
-
-::
-
-    $ git fetch $REMOTE $BRANCH
-    $ git merge FETCH_HEAD
-
-Certainly, $BRANCH in that case should be your current branch. If you
-want to merge a different branch into your current branch first update
-that non-current branch and then merge::
-
-    $ git fetch origin v1:v1  # Update v1
-    $ git pull --rebase origin master  # Update the current branch master
-                                       # using rebase instead of merge
-    $ git merge v1
-
-If you have not yet pushed commits on ``v1``, though, the scenario has
-to become a bit more complex. Git refuses to update
-non-fast-forwardable branch, and you don't want to do force-pull
-because that would remove your non-pushed commits and you would need
-to recover. So you want to rebase ``v1`` but you cannot rebase
-non-current branch. Hence, checkout ``v1`` and rebase it before
-merging::
-
-    $ git checkout v1
-    $ git pull --rebase origin v1
-    $ git checkout master
-    $ git pull --rebase origin master
-    $ git merge v1
-
-It is possible to configure git to make it fetch/pull a few branches
-or all branches at once, so you can simply run
-
-::
-
-    $ git pull origin
-
-or even
-
-::
-
-    $ git pull
-
-Default remote repository for fetching/pulling is ``origin``. Default
-set of references to fetch is calculated using matching algorithm: git
-fetches all branches having the same name on both ends.
-
-
-Push
-''''
-
-Pushing is a bit simpler. There is only one command ``push``. When you
-run
-
-::
-
-    $ git push origin v1 master
-
-git pushes local v1 to remote v1 and local master to remote master.
-The same as::
-
-    $ git push origin v1:v1 master:master
-
-Git pushes commits to the remote repo and updates remote-tracking
-branches. Git refuses to push commits that aren't fast-forwardable.
-You can force-push anyway, but please remember - you can force-push to
-your own repositories but don't force-push to public or shared repos.
-If you find git refuses to push commits that aren't fast-forwardable,
-better fetch and merge commits from the remote repo (or rebase your
-commits on top of the fetched commits), then push. Only force-push if
-you know what you do and why you do it. See the section `Commit
-editing and caveats`_ below.
-
-It is possible to configure git to make it push a few branches or all
-branches at once, so you can simply run
-
-::
-
-    $ git push origin
-
-or even
-
-::
-
-    $ git push
-
-Default remote repository for pushing is ``origin``. Default set of
-references to push in git before 2.0 is calculated using matching
-algorithm: git pushes all branches having the same name on both ends.
-Default set of references to push in git 2.0+ is calculated using
-simple algorithm: git pushes the current branch back to its
-@{upstream}.
-
-To configure git before 2.0 to the new behaviour run::
-
-$ git config push.default simple
-
-To configure git 2.0+ to the old behaviour run::
-
-$ git config push.default matching
-
-Git doesn't allow to push a branch if it's the current branch in the
-remote non-bare repository: git refuses to update remote working
-directory. You really should push only to bare repositories. For
-non-bare repositories git prefers pull-based workflow.
-
-When you want to deploy code on a remote host and can only use push
-(because your workstation is behind a firewall and you cannot pull
-from it) you do that in two steps using two repositories: you push
-from the workstation to a bare repo on the remote host, ssh to the
-remote host and pull from the bare repo to a non-bare deployment repo.
-
-That changed in git 2.3, but see `the blog post
-<https://github.com/blog/1957-git-2-3-has-been-released#push-to-deploy>`_
-for caveats; in 2.4 the push-to-deploy feature was `further improved
-<https://github.com/blog/1994-git-2-4-atomic-pushes-push-to-deploy-and-more#push-to-deploy-improvements>`_.
-
-
-Tags
-''''
-
-Git automatically fetches tags that point to commits being fetched
-during fetch/pull. To fetch all tags (and commits they point to) run
-``git fetch --tags origin``. To fetch some specific tags fetch them
-explicitly::
-
-    $ git fetch origin tag $TAG1 tag $TAG2...
-
-For example::
-
-    $ git fetch origin tag 1.4.2
-    $ git fetch origin v1:v1 tag 2.1.7
-
-Git doesn't automatically pushes tags. That allows you to have private
-tags. To push tags list them explicitly::
-
-    $ git push origin tag 1.4.2
-    $ git push origin v1 master tag 2.1.7
-
-Or push all tags at once::
-
-    $ git push --tags origin
-
-Don't move tags with ``git tag -f`` or remove tags with ``git tag -d``
-after they have been published.
-
-
-Private information
-'''''''''''''''''''
-
-When cloning/fetching/pulling/pushing git copies only database objects
-(commits, trees, files and tags) and symbolic references (branches and
-lightweight tags). Everything else is private to the repository and
-never cloned, updated or pushed. It's your config, your hooks, your
-private exclude file.
-
-If you want to distribute hooks, copy them to the working tree, add,
-commit, push and instruct the team to update and install the hooks
-manually.
-
-
-Commit editing and caveats
-==========================
-
-A warning not to edit published (pushed) commits also appears in
-documentation but it's repeated here anyway as it's very important.
-
-It is possible to recover from a forced push but it's PITA for the
-entire team. Please avoid it.
-
-To see what commits have not been published yet compare the head of the
-branch with its upstream remote-tracking branch::
-
-    $ git log origin/master..  # from origin/master to HEAD (of master)
-    $ git log origin/v1..v1  # from origin/v1 to the head of v1
-
-For every branch that has an upstream remote-tracking branch git
-maintains an alias @{upstream} (short version @{u}), so the commands
-above can be given as::
-
-    $ git log @{u}..
-    $ git log v1@{u}..v1
-
-To see the status of all branches::
-
-    $ git branch -avv
-
-To compare the status of local branches with a remote repo::
-
-    $ git remote show origin
-
-Read `how to recover from upstream rebase
-<https://git-scm.com/docs/git-rebase#_recovering_from_upstream_rebase>`_.
-It is in ``git help rebase``.
-
-On the other hand, don't be too afraid about commit editing. You can
-safely edit, reorder, remove, combine and split commits that haven't
-been pushed yet. You can even push commits to your own (backup) repo,
-edit them later and force-push edited commits to replace what have
-already been pushed. Not a problem until commits are in a public
-or shared repository.
-
-
-Undo
-====
-
-Whatever you do, don't panic. Almost anything in git can be undone.
-
-
-git checkout: restore file's content
-------------------------------------
-
-``git checkout``, for example, can be used to restore the content of
-file(s) to that one of a commit. Like this::
-
-    git checkout HEAD~ README
-
-The commands restores the contents of README file to the last but one
-commit in the current branch. By default the commit ID is simply HEAD;
-i.e. ``git checkout README`` restores README to the latest commit.
-
-(Do not use ``git checkout`` to view a content of a file in a commit,
-use ``git cat-file -p``; e.g. ``git cat-file -p HEAD~:path/to/README``).
-
-
-git reset: remove (non-pushed) commits
---------------------------------------
-
-``git reset`` moves the head of the current branch. The head can be
-moved to point to any commit but it's often used to remove a commit or
-a few (preferably, non-pushed ones) from the top of the branch - that
-is, to move the branch backward in order to undo a few (non-pushed)
-commits.
-
-``git reset`` has three modes of operation - soft, hard and mixed.
-Default is mixed. ProGit `explains
-<https://git-scm.com/book/en/Git-Tools-Reset-Demystified>`_ the
-difference very clearly. Bare repositories don't have indices or
-working trees so in a bare repo only soft reset is possible.
-
-
-Unstaging
-'''''''''
-
-Mixed mode reset with a path or paths can be used to unstage changes -
-that is, to remove from index changes added with ``git add`` for
-committing. See `The Book
-<https://git-scm.com/book/en/Git-Basics-Undoing-Things>`_ for details
-about unstaging and other undo tricks.
-
-
-git reflog: reference log
--------------------------
-
-Removing commits with ``git reset`` or moving the head of a branch
-sounds dangerous and it is. But there is a way to undo: another
-reset back to the original commit. Git doesn't remove commits
-immediately; unreferenced commits (in git terminology they are called
-"dangling commits") stay in the database for some time (default is two
-weeks) so you can reset back to it or create a new branch pointing to
-the original commit.
-
-For every move of a branch's head - with ``git commit``, ``git
-checkout``, ``git fetch``, ``git pull``, ``git rebase``, ``git reset``
-and so on - git stores a reference log (reflog for short). For every
-move git stores where the head was. Command ``git reflog`` can be used
-to view (and manipulate) the log.
-
-In addition to the moves of the head of every branch git stores the
-moves of the HEAD - a symbolic reference that (usually) names the
-current branch. HEAD is changed with ``git checkout $BRANCH``.
-
-By default ``git reflog`` shows the moves of the HEAD, i.e. the
-command is equivalent to ``git reflog HEAD``. To show the moves of the
-head of a branch use the command ``git reflog $BRANCH``.
-
-So to undo a ``git reset`` lookup the original commit in ``git
-reflog``, verify it with ``git show`` or ``git log`` and run ``git
-reset $COMMIT_ID``. Git stores the move of the branch's head in
-reflog, so you can undo that undo later again.
-
-In a more complex situation you'd want to move some commits along with
-resetting the head of the branch. Cherry-pick them to the new branch.
-For example, if you want to reset the branch ``master`` back to the
-original commit but preserve two commits created in the current branch
-do something like::
-
-    $ git branch save-master  # create a new branch saving master
-    $ git reflog  # find the original place of master
-    $ git reset $COMMIT_ID
-    $ git cherry-pick save-master~ save-master
-    $ git branch -D save-master  # remove temporary branch
-
-
-git revert: revert a commit
----------------------------
-
-``git revert`` reverts a commit or commits, that is, it creates a new
-commit or commits that revert(s) the effects of the given commits.
-It's the only way to undo published commits (``git commit --amend``,
-``git rebase`` and ``git reset`` change the branch in
-non-fast-forwardable ways so they should only be used for non-pushed
-commits.)
-
-There is a problem with reverting a merge commit. ``git revert`` can
-undo the code created by the merge commit but it cannot undo the fact
-of merge. See the discussion `How to revert a faulty merge
-<https://www.kernel.org/pub/software/scm/git/docs/howto/revert-a-faulty-merge.html>`_.
-
-
-One thing that cannot be undone
--------------------------------
-
-Whatever you undo, there is one thing that cannot be undone -
-overwritten uncommitted changes. Uncommitted changes don't belong to
-git so git cannot help preserving them.
-
-Most of the time git warns you when you're going to execute a command
-that overwrites uncommitted changes. Git doesn't allow you to switch
-branches with ``git checkout``. It stops you when you're going to
-rebase with non-clean working tree. It refuses to pull new commits
-over non-committed files.
-
-But there are commands that do exactly that - overwrite files in the
-working tree. Commands like ``git checkout $PATHs`` or ``git reset
---hard`` silently overwrite files including your uncommitted changes.
-
-With that in mind you can understand the stance "commit early, commit
-often". Commit as often as possible. Commit on every save in your
-editor or IDE. You can edit your commits before pushing - edit commit
-messages, change commits, reorder, combine, split, remove. But save
-your changes in git database, either commit changes or at least stash
-them with ``git stash``.
-
-
-Merge or rebase?
-================
-
-Internet is full of heated discussions on the topic: "merge or
-rebase?" Most of them are meaningless. When a DVCS is being used in a
-big team with a big and complex project with many branches there is
-simply no way to avoid merges. So the question's diminished to
-"whether to use rebase, and if yes - when to use rebase?" Considering
-that it is very much recommended not to rebase published commits the
-question's diminished even further: "whether to use rebase on
-non-pushed commits?"
-
-That small question is for the team to decide. To preserve the beauty
-of linear history it's recommended to use rebase when pulling, i.e. do
-``git pull --rebase`` or even configure automatic setup of rebase for
-every new branch::
-
-    $ git config branch.autosetuprebase always
-
-and configure rebase for existing branches::
-
-    $ git config branch.$NAME.rebase true
-
-For example::
-
-    $ git config branch.v1.rebase true
-    $ git config branch.master.rebase true
-
-After that ``git pull origin master`` becomes equivalent to ``git pull
---rebase origin master``.
-
-It is recommended to create new commits in a separate feature or topic
-branch while using rebase to update the mainline branch. When the
-topic branch is ready merge it into mainline. To avoid a tedious task
-of resolving large number of conflicts at once you can merge the topic
-branch to the mainline from time to time and switch back to the topic
-branch to continue working on it. The entire workflow would be
-something like::
-
-    $ git checkout -b issue-42  # create a new issue branch and switch to it
-        ...edit/test/commit...
-    $ git checkout master
-    $ git pull --rebase origin master  # update master from the upstream
-    $ git merge issue-42
-    $ git branch -d issue-42  # delete the topic branch
-    $ git push origin master
-
-When the topic branch is deleted only the label is removed, commits
-are stayed in the database, they are now merged into master::
-
-    o--o--o--o--o--M--< master - the mainline branch
-        \         /
-         --*--*--*             - the topic branch, now unnamed
-
-The topic branch is deleted to avoid cluttering branch namespace with
-small topic branches. Information on what issue was fixed or what
-feature was implemented should be in the commit messages.
-
-But even that small amount of rebasing could be too big in case of
-long-lived merged branches. Imagine you're doing work in both ``v1``
-and ``master`` branches, regularly merging ``v1`` into ``master``.
-After some time you will have a lot of merge and non-merge commits in
-``master``. Then you want to push your finished work to a shared
-repository and find someone has pushed a few commits to ``v1``. Now
-you have a choice of two equally bad alternatives: either you fetch
-and rebase ``v1`` and then have to recreate all you work in ``master``
-(reset ``master`` to the origin, merge ``v1`` and cherry-pick all
-non-merge commits from the old master); or merge the new ``v1`` and
-loose the beauty of linear history.
-
-
-Null-merges
-===========
-
-Git has a builtin merge strategy for what Python core developers call
-"null-merge"::
-
-    $ git merge -s ours v1  # null-merge v1 into master
-
-
-Branching models
-================
-
-Git doesn't assume any particular development model regarding
-branching and merging. Some projects prefer to graduate patches from
-the oldest branch to the newest, some prefer to cherry-pick commits
-backwards, some use squashing (combining a number of commits into
-one). Anything is possible.
-
-There are a few examples to start with. `git help workflows
-<https://www.kernel.org/pub/software/scm/git/docs/gitworkflows.html>`_
-describes how the very git authors develop git.
-
-ProGit book has a few chapters devoted to branch management in
-different projects: `Git Branching - Branching Workflows
-<https://git-scm.com/book/en/Git-Branching-Branching-Workflows>`_ and
-`Distributed Git - Contributing to a Project
-<https://git-scm.com/book/en/Distributed-Git-Contributing-to-a-Project>`_.
-
-There is also a well-known article `A successful Git branching model
-<http://nvie.com/posts/a-successful-git-branching-model/>`_ by Vincent
-Driessen. It recommends a set of very detailed rules on creating and
-managing mainline, topic and bugfix branches. To support the model the
-author implemented `git flow <https://github.com/nvie/gitflow>`_
-extension.
-
-
-Advanced configuration
-======================
-
-Line endings
-------------
-
-Git has builtin mechanisms to handle line endings between platforms
-with different end-of-line styles. To allow git to do CRLF conversion
-assign ``text`` attribute to files using `.gitattributes
-<https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html>`_.
-For files that have to have specific line endings assign ``eol``
-attribute. For binary files the attribute is, naturally, ``binary``.
-
-For example::
-
-    $ cat .gitattributes
-    *.py text
-    *.txt text
-    *.png binary
-    /readme.txt eol=CRLF
-
-To check what attributes git uses for files use ``git check-attr``
-command. For example::
-
-$ git check-attr -a -- \*.py
-
-
-Useful assets
--------------
-
-`GitAlias <http://gitalias.com/>`_ (`repository
-<https://github.com/GitAlias/gitalias>`_) is a big collection of
-aliases. A careful selection of aliases for frequently used commands
-could save you a lot of keystrokes!
-
-`GitIgnore <https://www.gitignore.io/>`_ and
-https://github.com/github/gitignore are collections of ``.gitignore``
-files for all kinds of IDEs and programming languages. Python
-included!
-
-`pre-commit <http://pre-commit.com/>`_ (`repositories
-<https://github.com/pre-commit>`_) is a framework for managing and
-maintaining multi-language pre-commit hooks. The framework is written
-in Python and has a lot of plugins for many programming languages.
-
-
-Advanced topics
-===============
-
-Staging area
-------------
-
-Staging area aka index aka cache is a distinguishing feature of git.
-Staging area is where git collects patches before committing them.
-Separation between collecting patches and commit phases provides a
-very useful feature of git: you can review collected patches before
-commit and even edit them - remove some hunks, add new hunks and
-review again.
-
-To add files to the index use ``git add``. Collecting patches before
-committing means you need to do that for every change, not only to add
-new (untracked) files. To simplify committing in case you just want to
-commit everything without reviewing run ``git commit --all`` (or just
-``-a``) - the command adds every changed tracked file to the index and
-then commit. To commit a file or files regardless of patches collected
-in the index run ``git commit [--only|-o] -- $FILE...``.
-
-To add hunks of patches to the index use ``git add --patch`` (or just
-``-p``). To remove collected files from the index use ``git reset HEAD
--- $FILE...`` To add/inspect/remove collected hunks use ``git add
---interactive`` (``-i``).
-
-To see the diff between the index and the last commit (i.e., collected
-patches) use ``git diff --cached``. To see the diff between the
-working tree and the index (i.e., uncollected patches) use just ``git
-diff``. To see the diff between the working tree and the last commit
-(i.e., both collected and uncollected patches) run ``git diff HEAD``.
-
-See `WhatIsTheIndex
-<https://git.wiki.kernel.org/index.php/WhatIsTheIndex>`_ and
-`IndexCommandQuickref
-<https://git.wiki.kernel.org/index.php/IndexCommandQuickref>`_ in Git
-Wiki.
-
-
-Root
-----
-
-Git switches to the root (top-level directory of the project where
-``.git`` subdirectory exists) before running any command. Git
-remembers though the directory that was current before the switch.
-Some programs take into account the current directory. E.g., ``git
-status`` shows file paths of changed and unknown files relative to the
-current directory; ``git grep`` searches below the current directory;
-``git apply`` applies only those hunks from the patch that touch files
-below the current directory.
-
-But most commands run from the root and ignore the current directory.
-Imagine, for example, that you have two work trees, one for the branch
-``v1`` and the other for ``master``. If you want to merge ``v1`` from
-a subdirectory inside the second work tree you must write commands as
-if you're in the top-level dir. Let take two work trees,
-``project-v1`` and ``project``, for example::
-
-    $ cd project/subdirectory
-    $ git fetch ../project-v1 v1:v1
-    $ git merge v1
-
-Please note the path in ``git fetch ../project-v1 v1:v1`` is
-``../project-v1`` and not ``../../project-v1`` despite the fact that
-we run the commands from a subdirectory, not from the root.
-
-
-ReReRe
-------
-
-Rerere is a mechanism that helps to resolve repeated merge conflicts.
-The most frequent source of recurring merge conflicts are topic
-branches that are merged into mainline and then the merge commits are
-removed; that's often performed to test the topic branches and train
-rerere; merge commits are removed to have clean linear history and
-finish the topic branch with only one last merge commit.
-
-Rerere works by remembering the states of tree before and after a
-successful commit. That way rerere can automatically resolve conflicts
-if they appear in the same files.
-
-Rerere can be used manually with ``git rerere`` command but most often
-it's used automatically. Enable rerere with these commands in a
-working tree::
-
-    $ git config rerere.enabled true
-    $ git config rerere.autoupdate true
-
-You don't need to turn rerere on globally - you don't want rerere in
-bare repositories or single-branch repositories; you only need rerere
-in repos where you often perform merges and resolve merge conflicts.
-
-See `Rerere <https://git-scm.com/book/en/Git-Tools-Rerere>`_ in The
-Book.
-
-
-Database maintenance
---------------------
-
-Git object database and other files/directories under ``.git`` require
-periodic maintenance and cleanup. For example, commit editing left
-unreferenced objects (dangling objects, in git terminology) and these
-objects should be pruned to avoid collecting cruft in the DB. The
-command ``git gc`` is used for maintenance. Git automatically runs
-``git gc --auto`` as a part of some commands to do quick maintenance.
-Users are recommended to run ``git gc --aggressive`` from time to
-time; ``git help gc`` recommends to run it  every few hundred
-changesets; for more intensive projects it should be something like
-once a week and less frequently (biweekly or monthly) for lesser
-active projects.
-
-``git gc --aggressive`` not only removes dangling objects, it also
-repacks object database into indexed and better optimized pack(s); it
-also packs symbolic references (branches and tags). Another way to do
-it is to run ``git repack``.
-
-There is a well-known `message
-<https://gcc.gnu.org/ml/gcc/2007-12/msg00165.html>`_ from Linus
-Torvalds regarding "stupidity" of ``git gc --aggressive``. The message
-can safely be ignored now. It is old and outdated, ``git gc
---aggressive`` became much better since that time.
-
-For those who still prefer ``git repack`` over ``git gc --aggressive``
-the recommended parameters are ``git repack -a -d -f --depth=20
---window=250``. See `this detailed experiment
-<http://vcscompare.blogspot.ru/2008/06/git-repack-parameters.html>`_
-for explanation of the effects of these parameters.
-
-From time to time run ``git fsck [--strict]`` to verify integrity of
-the database. ``git fsck`` may produce a list of dangling objects;
-that's not an error, just a reminder to perform regular maintenance.
-
-
-Tips and tricks
-===============
-
-Command-line options and arguments
-----------------------------------
-
-`git help cli
-<https://www.kernel.org/pub/software/scm/git/docs/gitcli.html>`_
-recommends not to combine short options/flags. Most of the times
-combining works: ``git commit -av`` works perfectly, but there are
-situations when it doesn't. E.g., ``git log -p -5`` cannot be combined
-as ``git log -p5``.
-
-Some options have arguments, some even have default arguments. In that
-case the argument for such option must be spelled in a sticky way:
-``-Oarg``, never ``-O arg`` because for an option that has a default
-argument the latter means "use default value for option ``-O`` and
-pass ``arg`` further to the option parser". For example, ``git grep``
-has an option ``-O`` that passes a list of names of the found files to
-a program; default program for ``-O`` is a pager (usually ``less``),
-but you can use your editor::
-
-    $ git grep -Ovim  # but not -O vim
-
-BTW, if git is instructed to use ``less`` as the pager (i.e., if pager
-is not configured in git at all it uses ``less`` by default, or if it
-gets ``less`` from GIT_PAGER or PAGER environment variables, or if it
-was configured with ``git config [--global] core.pager less``, or
-``less`` is used in the command ``git grep -Oless``) ``git grep``
-passes ``+/$pattern`` option to ``less`` which is quite convenient.
-Unfortunately, ``git grep`` doesn't pass the pattern if the pager is
-not exactly ``less``, even if it's ``less`` with parameters (something
-like ``git config [--global] core.pager less -FRSXgimq``); fortunately,
-``git grep -Oless`` always passes the pattern.
-
-
-bash/zsh completion
--------------------
-
-It's a bit hard to type ``git rebase --interactive --preserve-merges
-HEAD~5`` manually even for those who are happy to use command-line,
-and this is where shell completion is of great help. Bash/zsh come
-with programmable completion, often automatically installed and
-enabled, so if you have bash/zsh and git installed, chances are you
-are already done - just go and use it at the command-line.
-
-If you don't have necessary bits installed, install and enable
-bash_completion package. If you want to upgrade your git completion to
-the latest and greatest download necessary file from `git contrib
-<https://git.kernel.org/cgit/git/git.git/tree/contrib/completion>`_.
-
-Git-for-windows comes with git-bash for which bash completion is
-installed and enabled.
-
-
-bash/zsh prompt
----------------
-
-For command-line lovers shell prompt can carry a lot of useful
-information. To include git information in the prompt use
-`git-prompt.sh
-<https://git.kernel.org/cgit/git/git.git/tree/contrib/completion/git-prompt.sh>`_.
-Read the detailed instructions in the file.
-
-Search the Net for "git prompt" to find other prompt variants.
-
-
-SSH connection sharing
-----------------------
-
-SSH connection sharing is a feature of OpenSSH and perhaps derivatives
-like PuTTY. SSH connection sharing is a way to decrease ssh client
-startup time by establishing one connection and reusing it for all
-subsequent clients connecting to the same server. SSH connection
-sharing can be used to speedup a lot of short ssh sessions like scp,
-sftp, rsync and of course git over ssh. If you regularly
-fetch/pull/push from/to remote repositories accessible over ssh then
-using ssh connection sharing is recommended.
-
-To turn on ssh connection sharing add something like this to your
-~/.ssh/config::
-
-    Host *
-    ControlMaster auto
-    ControlPath ~/.ssh/mux-%r@%h:%p
-    ControlPersist 600
-
-See `OpenSSH wikibook
-<https://en.wikibooks.org/wiki/OpenSSH/Cookbook/Multiplexing>`_ and
-`search <https://www.google.com/search?q=ssh+connection+sharing>`_ for
-more information.
-
-SSH connection sharing can be used at GitHub, GitLab and SourceForge
-repositories, but please be advised that BitBucket doesn't allow it
-and forcibly closes master connection after a short inactivity period
-so you will see errors like this from ssh: "Connection to bitbucket.org
-closed by remote host."
-
-
-git on server
-=============
-
-The simplest way to publish a repository or a group of repositories is
-``git daemon``. The daemon provides anonymous access, by default it is
-read-only. The repositories are accessible by git protocol (git://
-URLs). Write access can be enabled but the protocol lacks any
-authentication means, so it should be enabled only within a trusted
-LAN. See ``git help daemon`` for details.
-
-Git over ssh provides authentication and repo-level authorisation as
-repositories can be made user- or group-writeable (see parameter
-``core.sharedRepository`` in ``git help config``). If that's too
-permissive or too restrictive for some project's needs there is a
-wrapper `gitolite <http://gitolite.com/gitolite/index.html>`_ that can
-be configured to allow access with great granularity; gitolite is
-written in Perl and has a lot of documentation.
-
-Web interface to browse repositories can be created using `gitweb
-<https://git.kernel.org/cgit/git/git.git/tree/gitweb>`_ or `cgit
-<http://git.zx2c4.com/cgit/about/>`_. Both are CGI scripts (written in
-Perl and C). In addition to web interface both provide read-only dumb
-http access for git (http(s):// URLs). `Klaus
-<https://pypi.python.org/pypi/klaus>`_ is a small and simple WSGI web
-server that implements both web interface and git smart HTTP
-transport; supports Python 2 and Python 3, performs syntax
-highlighting.
-
-There are also more advanced web-based development environments that
-include ability to manage users, groups and projects; private,
-group-accessible and public repositories; they often include issue
-trackers, wiki pages, pull requests and other tools for development
-and communication. Among these environments are `Kallithea
-<https://kallithea-scm.org/>`_ and `pagure <https://pagure.io/>`_,
-both are written in Python; pagure was written by Fedora developers
-and is being used to develop some Fedora projects. `GitPrep
-<http://gitprep.yukikimoto.com/>`_ is yet another GitHub clone,
-written in Perl. `Gogs <https://gogs.io/>`_ is written in Go. `GitBucket
-<https://gitbucket.github.io/gitbucket-news/about/>`_ is written in
-Scala. `RocketGit <https://rocketgit.com/>`_ is AGPL-licensed
-development environment written in PHP (there are plans to rewrite
-critical parts in C).
-
-And last but not least, `GitLab <https://about.gitlab.com/>`_. It's
-perhaps the most advanced web-based development environment for git.
-Written in Ruby, community edition is free and open source (MIT
-license).
-
-
-From Mercurial to git
-=====================
-
-There are many tools to convert Mercurial repositories to git. The
-most famous are, probably, `hg-git <https://hg-git.github.io/>`_ and
-`fast-export <http://repo.or.cz/w/fast-export.git>`_ (many years ago
-it was known under the name ``hg2git``).
-
-But a better tool, perhaps the best, is `git-remote-hg
-<https://github.com/felipec/git-remote-hg>`_. It provides transparent
-bidirectional (pull and push) access to Mercurial repositories from
-git. Its author wrote a `comparison of alternatives
-<https://github.com/felipec/git/wiki/Comparison-of-git-remote-hg-alternatives>`_
-that seems to be mostly objective.
-
-To use git-remote-hg, install or clone it, add to your PATH (or copy
-script ``git-remote-hg`` to a directory that's already in PATH) and
-prepend ``hg::`` to Mercurial URLs. For example::
-
-    $ git clone https://github.com/felipec/git-remote-hg.git
-    $ PATH=$PATH:"`pwd`"/git-remote-hg
-    $ git clone hg::https://hg.python.org/peps/ PEPs
-
-To work with the repository just use regular git commands including
-``git fetch/pull/push``.
-
-To start converting your Mercurial habits to git see the page
-`Mercurial for Git users
-<https://www.mercurial-scm.org/wiki/GitConcepts>`_ at Mercurial wiki.
-At the second half of the page there is a table that lists
-corresponding Mercurial and git commands. Should work perfectly in
-both directions.
-
-Python Developer's Guide also has a chapter `Mercurial for git
-developers <https://docs.python.org/devguide/gitdevs.html>`_ that
-documents a few differences between git and hg.
-
-
-Git and GitHub
-==============
-
-`gitsome <https://github.com/donnemartin/gitsome>`_ - Git/GitHub
-command line interface (CLI). Written in Python, work on MacOS, Unix,
-Windows. Git/GitHub CLI with autocomplete, includes many GitHub
-integrated commands that work with all shells, builtin xonsh with
-Python REPL to run Python commands alongside shell commands, command
-history, customizable highlighting, thoroughly documented.