I have only skimmed the first half but it looks really good. On Sat, Sep 12, 2015 at 8:12 AM, Brett Cannon <br...@python.org> wrote:
> I have not had a chance to read Oleg's PEP, but the devguide has the > reverse docs at https://docs.python.org/devguide/gitdevs.html so we have > the VCS docs down pat. :) > > On Sat, Sep 12, 2015, 06:59 Oleg Broytman <p...@phdru.name> wrote: > >> PEP: XXX >> Title: Collecting information about git >> Version: $Revision$ >> Last-Modified: $Date$ >> Author: Oleg Broytman <p...@phdru.name> >> Status: Draft >> Type: Informational >> Content-Type: text/x-rst >> Created: 01-Jun-2015 >> Post-History: 12-Sep-2015 >> >> Abstract >> ======== >> >> This Informational PEP 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. >> >> The plan is to extend the PEP in the future collecting information >> about equivalence of Mercurial and git scenarios to help migrating >> Python development from Mercurial to git. >> >> The author of the PEP doesn't currently plan to write a Process PEP on >> migration Python development from Mercurial to git. >> >> >> 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/everyday.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>`_. >> >> >> 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>`_ or `msysGit >> <https://github.com/msysgit/msysgit/releases>`_. >> >> MacOS X: use git installed with `XCode >> <https://developer.apple.com/xcode/downloads/>`_ 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>`_ 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.n...@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`` >> <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. >> >> >> Updating local and remote-tracking branches >> ------------------------------------------- >> >> 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. The author of the PEP >> recommends to use rebase when pulling, i.e. always 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. >> >> >> 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 >> >> >> 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 >> >> >> 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. >> >> >> 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-branche 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. >> >> >> 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). >> >> 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. `Gogs >> <http://gogs.io/>`_ is written in Go; there is a fork `Gitea >> <http://gitea.io/>`_. >> >> 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://mercurial.selenic.com/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. >> >> >> Copyright >> ========= >> >> This document has been placed in the public domain. >> >> >> >> .. >> Local Variables: >> mode: indented-text >> indent-tabs-mode: nil >> sentence-end-double-space: t >> fill-column: 70 >> coding: utf-8 >> End: >> vim: set fenc=us-ascii tw=70 : >> _______________________________________________ >> Python-Dev mailing list >> Python-Dev@python.org >> https://mail.python.org/mailman/listinfo/python-dev >> Unsubscribe: >> https://mail.python.org/mailman/options/python-dev/brett%40python.org >> > > _______________________________________________ > Python-Dev mailing list > Python-Dev@python.org > https://mail.python.org/mailman/listinfo/python-dev > Unsubscribe: > https://mail.python.org/mailman/options/python-dev/guido%40python.org > > -- --Guido van Rossum (python.org/~guido)
_______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com