A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from http://mail.python.org/pipermail/python-dev/attachments/20150912/32b85877/attachment-0001.html below:

<p dir="ltr">I have not had a chance to read Oleg's PEP, but the devguide has the reverse docs at <a href="https://docs.python.org/devguide/gitdevs.html">https://docs.python.org/devguide/gitdevs.html</a> so we have the VCS docs down pat. :)</p>
<br><div class="gmail_quote"><div dir="ltr">On Sat, Sep 12, 2015, 06:59 Oleg Broytman <<a href="mailto:phd@phdru.name">phd@phdru.name</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">PEP: XXX<br>
Title: Collecting information about git<br>
Version: $Revision$<br>
Last-Modified: $Date$<br>
Author: Oleg Broytman <<a href="mailto:phd@phdru.name" target="_blank">phd@phdru.name</a>><br>
Status: Draft<br>
Type: Informational<br>
Content-Type: text/x-rst<br>
Created: 01-Jun-2015<br>
Post-History: 12-Sep-2015<br>
<br>
Abstract<br>
========<br>
<br>
This Informational PEP collects information about git. There is, of<br>
course, a lot of documentation for git, so the PEP concentrates on<br>
more complex (and more related to Python development) issues,<br>
scenarios and examples.<br>
<br>
The plan is to extend the PEP in the future collecting information<br>
about equivalence of Mercurial and git scenarios to help migrating<br>
Python development from Mercurial to git.<br>
<br>
The author of the PEP doesn't currently plan to write a Process PEP on<br>
migration Python development from Mercurial to git.<br>
<br>
<br>
Documentation<br>
=============<br>
<br>
Git is accompanied with a lot of documentation, both online and<br>
offline.<br>
<br>
<br>
Documentation for starters<br>
--------------------------<br>
<br>
Git Tutorial: `part 1<br>
<<a href="https://www.kernel.org/pub/software/scm/git/docs/gittutorial.html" rel="noreferrer" target="_blank">https://www.kernel.org/pub/software/scm/git/docs/gittutorial.html</a>>`_,<br>
`part 2<br>
<<a href="https://www.kernel.org/pub/software/scm/git/docs/gittutorial-2.html" rel="noreferrer" target="_blank">https://www.kernel.org/pub/software/scm/git/docs/gittutorial-2.html</a>>`_.<br>
<br>
`Git User's manual<br>
<<a href="https://www.kernel.org/pub/software/scm/git/docs/user-manual.html" rel="noreferrer" target="_blank">https://www.kernel.org/pub/software/scm/git/docs/user-manual.html</a>>`_.<br>
`Everyday GIT With 20 Commands Or So<br>
<<a href="https://www.kernel.org/pub/software/scm/git/docs/everyday.html" rel="noreferrer" target="_blank">https://www.kernel.org/pub/software/scm/git/docs/everyday.html</a>>`_.<br>
`Git workflows<br>
<<a href="https://www.kernel.org/pub/software/scm/git/docs/gitworkflows.html" rel="noreferrer" target="_blank">https://www.kernel.org/pub/software/scm/git/docs/gitworkflows.html</a>>`_.<br>
<br>
<br>
Advanced documentation<br>
----------------------<br>
<br>
`Git Magic<br>
<<a href="http://www-cs-students.stanford.edu/~blynn/gitmagic/index.html" rel="noreferrer" target="_blank">http://www-cs-students.stanford.edu/~blynn/gitmagic/index.html</a>>`_,<br>
with a number of translations.<br>
<br>
`Pro Git <<a href="https://git-scm.com/book" rel="noreferrer" target="_blank">https://git-scm.com/book</a>>`_. The Book about git. Buy it at<br>
Amazon or download in PDF, mobi, or ePub form. It has translations to<br>
many different languages. Download Russian translation from `GArik<br>
<<a href="https://github.com/GArik/progit/wiki" rel="noreferrer" target="_blank">https://github.com/GArik/progit/wiki</a>>`_.<br>
<br>
`Git Wiki <<a href="https://git.wiki.kernel.org/index.php/Main_Page" rel="noreferrer" target="_blank">https://git.wiki.kernel.org/index.php/Main_Page</a>>`_.<br>
<br>
<br>
Offline documentation<br>
---------------------<br>
<br>
Git has builtin help: run ``git help $TOPIC``. For example, run<br>
``git help git`` or ``git help help``.<br>
<br>
<br>
Quick start<br>
===========<br>
<br>
Download and installation<br>
-------------------------<br>
<br>
Unix users: `download and install using your package manager<br>
<<a href="https://git-scm.com/download/linux" rel="noreferrer" target="_blank">https://git-scm.com/download/linux</a>>`_.<br>
<br>
Microsoft Windows: download `git-for-windows<br>
<<a href="https://github.com/git-for-windows/git/releases" rel="noreferrer" target="_blank">https://github.com/git-for-windows/git/releases</a>>`_ or `msysGit<br>
<<a href="https://github.com/msysgit/msysgit/releases" rel="noreferrer" target="_blank">https://github.com/msysgit/msysgit/releases</a>>`_.<br>
<br>
MacOS X: use git installed with `XCode<br>
<<a href="https://developer.apple.com/xcode/downloads/" rel="noreferrer" target="_blank">https://developer.apple.com/xcode/downloads/</a>>`_ or download from<br>
`MacPorts <<a href="https://www.macports.org/ports.php?by=name&substr=git" rel="noreferrer" target="_blank">https://www.macports.org/ports.php?by=name&substr=git</a>>`_ or<br>
`git-osx-installer<br>
<<a href="http://sourceforge.net/projects/git-osx-installer/files/" rel="noreferrer" target="_blank">http://sourceforge.net/projects/git-osx-installer/files/</a>>`_ or<br>
install git with `Homebrew <<a href="http://brew.sh/" rel="noreferrer" target="_blank">http://brew.sh/</a>>`_: ``brew install git``.<br>
<br>
`git-cola <<a href="https://git-cola.github.io/index.html" rel="noreferrer" target="_blank">https://git-cola.github.io/index.html</a>>`_ is a Git GUI<br>
written in Python and GPL licensed. Linux, Windows, MacOS X.<br>
<br>
`TortoiseGit <<a href="https://tortoisegit.org/" rel="noreferrer" target="_blank">https://tortoisegit.org/</a>>`_ is a Windows Shell Interface<br>
to Git based on TortoiseSVN; open source.<br>
<br>
<br>
Initial configuration<br>
---------------------<br>
<br>
This simple code is often appears in documentation, but it is<br>
important so let repeat it here. Git stores author and committer<br>
names/emails in every commit, so configure your real name and<br>
preferred email::<br>
<br>
  Â  $ git config --global <a href="http://user.name" rel="noreferrer" target="_blank">user.name</a> "User Name"<br>
  Â  $ git config --global user.email <a href="mailto:user.name@example.org" target="_blank">user.name@example.org</a><br>
<br>
<br>
Examples in this PEP<br>
====================<br>
<br>
Examples of git commands in this PEP use the following approach. It is<br>
supposed that you, the user, works with a local repository named<br>
``python`` that has an upstream remote repo named ``origin``. Your<br>
local repo has two branches ``v1`` and ``master``. For most examples<br>
the currently checked out branch is ``master``. That is, it's assumed<br>
you have done something like that::<br>
<br>
  Â  $ git clone <a href="https://git.python.org/python.git" rel="noreferrer" target="_blank">https://git.python.org/python.git</a><br>
  Â  $ cd python<br>
  Â  $ git branch v1 origin/v1<br>
<br>
The first command clones remote repository into local directory<br>
`python``, creates a new local branch master, sets<br>
remotes/origin/master as its upstream remote-tracking branch and<br>
checks it out into the working directory.<br>
<br>
The last command creates a new local branch v1 and sets<br>
remotes/origin/v1 as its upstream remote-tracking branch.<br>
<br>
The same result can be achieved with commands::<br>
<br>
  Â  $ git clone -b v1 <a href="https://git.python.org/python.git" rel="noreferrer" target="_blank">https://git.python.org/python.git</a><br>
  Â  $ cd python<br>
  Â  $ git checkout --track origin/master<br>
<br>
The last command creates a new local branch master, sets<br>
remotes/origin/master as its upstream remote-tracking branch and<br>
checks it out into the working directory.<br>
<br>
<br>
Branches and branches<br>
=====================<br>
<br>
Git terminology can be a bit misleading. Take, for example, the term<br>
"branch". In git it has two meanings. A branch is a directed line of<br>
commits (possibly with merges). And a branch is a label or a pointer<br>
assigned to a line of commits. It is important to distinguish when you<br>
talk about commits and when about their labels. Lines of commits are<br>
by itself unnamed and are usually only lengthening and merging.<br>
Labels, on the other hand, can be created, moved, renamed and deleted<br>
freely.<br>
<br>
<br>
Remote repositories and remote branches<br>
=======================================<br>
<br>
Remote-tracking branches are branches (pointers to commits) in your<br>
local repository. They are there for git (and for you) to remember<br>
what branches and commits have been pulled from and pushed to what<br>
remote repos (you can pull from and push to many remotes).<br>
Remote-tracking branches live under ``remotes/$REMOTE`` namespaces,<br>
e.g. ``remotes/origin/master``.<br>
<br>
To see the status of remote-tracking branches run::<br>
<br>
  Â  $ git branch -rv<br>
<br>
To see local and remote-tracking branches (and tags) pointing to<br>
commits::<br>
<br>
  Â  $ git log --decorate<br>
<br>
You never do your own development on remote-tracking branches. You<br>
create a local branch that has a remote branch as upstream and do<br>
development on that local branch. On push git pushes commits to the<br>
remote repo and updates remote-tracking branches, on pull git fetches<br>
commits from the remote repo, updates remote-tracking branches and<br>
fast-forwards, merges or rebases local branches.<br>
<br>
When you do an initial clone like this::<br>
<br>
  Â  $ git clone -b v1 <a href="https://git.python.org/python.git" rel="noreferrer" target="_blank">https://git.python.org/python.git</a><br>
<br>
git clones remote repository ``<a href="https://git.python.org/python.git" rel="noreferrer" target="_blank">https://git.python.org/python.git``</a> to<br>
directory ``python``, creates a remote named ``origin``, creates<br>
remote-tracking branches, creates a local branch ``v1``, configure it<br>
to track upstream remotes/origin/v1 branch and checks out ``v1`` into<br>
the working directory.<br>
<br>
<br>
Updating local and remote-tracking branches<br>
-------------------------------------------<br>
<br>
There is a major difference between<br>
<br>
::<br>
<br>
  Â  $ git fetch $REMOTE $BRANCH<br>
<br>
and<br>
<br>
::<br>
<br>
  Â  $ git fetch $REMOTE $BRANCH:$BRANCH<br>
<br>
The first command fetches commits from the named $BRANCH in the<br>
$REMOTE repository that are not in your repository, updates<br>
remote-tracking branch and leaves the id (the hash) of the head commit<br>
in file .git/FETCH_HEAD.<br>
<br>
The second command fetches commits from the named $BRANCH in the<br>
$REMOTE repository that are not in your repository and updates both<br>
the local branch $BRANCH and its upstream remote-tracking branch. But<br>
it refuses to update branches in case of non-fast-forward. And it<br>
refuses to update the current branch (currently checked out branch,<br>
where HEAD is pointing to).<br>
<br>
The first command is used internally by ``git pull``.<br>
<br>
::<br>
<br>
  Â  $ git pull $REMOTE $BRANCH<br>
<br>
is equivalent to<br>
<br>
::<br>
<br>
  Â  $ git fetch $REMOTE $BRANCH<br>
  Â  $ git merge FETCH_HEAD<br>
<br>
Certainly, $BRANCH in that case should be your current branch. If you<br>
want to merge a different branch into your current branch first update<br>
that non-current branch and then merge::<br>
<br>
  Â  $ git fetch origin v1:v1  # Update v1<br>
  Â  $ git pull --rebase origin master  # Update the current branch master<br>
  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â # using rebase instead of merge<br>
  Â  $ git merge v1<br>
<br>
If you have not yet pushed commits on ``v1``, though, the scenario has<br>
to become a bit more complex. Git refuses to update<br>
non-fast-forwardable branch, and you don't want to do force-pull<br>
because that would remove your non-pushed commits and you would need<br>
to recover. So you want to rebase ``v1`` but you cannot rebase<br>
non-current branch. Hence, checkout ``v1`` and rebase it before<br>
merging::<br>
<br>
  Â  $ git checkout v1<br>
  Â  $ git pull --rebase origin v1<br>
  Â  $ git checkout master<br>
  Â  $ git pull --rebase origin master<br>
  Â  $ git merge v1<br>
<br>
It is possible to configure git to make it fetch/pull a few branches<br>
or all branches at once, so you can simply run<br>
<br>
::<br>
<br>
  Â  $ git pull origin<br>
<br>
or even<br>
<br>
::<br>
<br>
  Â  $ git pull<br>
<br>
Default remote repository for fetching/pulling is ``origin``. Default<br>
set of references to fetch is calculated using matching algorithm: git<br>
fetches all branches having the same name on both ends.<br>
<br>
<br>
Push<br>
''''<br>
<br>
Pushing is a bit simpler. There is only one command ``push``. When you<br>
run<br>
<br>
::<br>
<br>
  Â  $ git push origin v1 master<br>
<br>
git pushes local v1 to remote v1 and local master to remote master.<br>
The same as::<br>
<br>
  Â  $ git push origin v1:v1 master:master<br>
<br>
Git pushes commits to the remote repo and updates remote-tracking<br>
branches. Git refuses to push commits that aren't fast-forwardable.<br>
You can force-push anyway, but please remember - you can force-push to<br>
your own repositories but don't force-push to public or shared repos.<br>
If you find git refuses to push commits that aren't fast-forwardable,<br>
better fetch and merge commits from the remote repo (or rebase your<br>
commits on top of the fetched commits), then push. Only force-push if<br>
you know what you do and why you do it. See the section `Commit<br>
editing and caveats`_ below.<br>
<br>
It is possible to configure git to make it push a few branches or all<br>
branches at once, so you can simply run<br>
<br>
::<br>
<br>
  Â  $ git push origin<br>
<br>
or even<br>
<br>
::<br>
<br>
  Â  $ git push<br>
<br>
Default remote repository for pushing is ``origin``. Default set of<br>
references to push in git before 2.0 is calculated using matching<br>
algorithm: git pushes all branches having the same name on both ends.<br>
Default set of references to push in git 2.0+ is calculated using<br>
simple algorithm: git pushes the current branch back to its<br>
@{upstream}.<br>
<br>
To configure git before 2.0 to the new behaviour run::<br>
<br>
$ git config push.default simple<br>
<br>
To configure git 2.0+ to the old behaviour run::<br>
<br>
$ git config push.default matching<br>
<br>
Git doesn't allow to push a branch if it's the current branch in the<br>
remote non-bare repository: git refuses to update remote working<br>
directory. You really should push only to bare repositories. For<br>
non-bare repositories git prefers pull-based workflow.<br>
<br>
When you want to deploy code on a remote host and can only use push<br>
(because your workstation is behind a firewall and you cannot pull<br>
from it) you do that in two steps using two repositories: you push<br>
from the workstation to a bare repo on the remote host, ssh to the<br>
remote host and pull from the bare repo to a non-bare deployment repo.<br>
<br>
That changed in git 2.3, but see `the blog post<br>
<<a href="https://github.com/blog/1957-git-2-3-has-been-released#push-to-deploy" rel="noreferrer" target="_blank">https://github.com/blog/1957-git-2-3-has-been-released#push-to-deploy</a>>`_<br>
for caveats; in 2.4 the push-to-deploy feature was `further improved<br>
<<a href="https://github.com/blog/1994-git-2-4-atomic-pushes-push-to-deploy-and-more#push-to-deploy-improvements" rel="noreferrer" target="_blank">https://github.com/blog/1994-git-2-4-atomic-pushes-push-to-deploy-and-more#push-to-deploy-improvements</a>>`_.<br>
<br>
<br>
Tags<br>
''''<br>
<br>
Git automatically fetches tags that point to commits being fetched<br>
during fetch/pull. To fetch all tags (and commits they point to) run<br>
``git fetch --tags origin``. To fetch some specific tags fetch them<br>
explicitly::<br>
<br>
  Â  $ git fetch origin tag $TAG1 tag $TAG2...<br>
<br>
For example::<br>
<br>
  Â  $ git fetch origin tag 1.4.2<br>
  Â  $ git fetch origin v1:v1 tag 2.1.7<br>
<br>
Git doesn't automatically pushes tags. That allows you to have private<br>
tags. To push tags list them explicitly::<br>
<br>
  Â  $ git push origin tag 1.4.2<br>
  Â  $ git push origin v1 master tag 2.1.7<br>
<br>
Or push all tags at once::<br>
<br>
  Â  $ git push --tags origin<br>
<br>
Don't move tags with ``git tag -f`` or remove tags with ``git tag -d``<br>
after they have been published.<br>
<br>
<br>
Private information<br>
'''''''''''''''''''<br>
<br>
When cloning/fetching/pulling/pushing git copies only database objects<br>
(commits, trees, files and tags) and symbolic references (branches and<br>
lightweight tags). Everything else is private to the repository and<br>
never cloned, updated or pushed. It's your config, your hooks, your<br>
private exclude file.<br>
<br>
If you want to distribute hooks, copy them to the working tree, add,<br>
commit, push and instruct the team to update and install the hooks<br>
manually.<br>
<br>
<br>
Commit editing and caveats<br>
==========================<br>
<br>
A warning not to edit published (pushed) commits also appears in<br>
documentation but it's repeated here anyway as it's very important.<br>
<br>
It is possible to recover from a forced push but it's PITA for the<br>
entire team. Please avoid it.<br>
<br>
To see what commits have not been published yet compare the head of the<br>
branch with its upstream remote-tracking branch::<br>
<br>
  Â  $ git log origin/master..  # from origin/master to HEAD (of master)<br>
  Â  $ git log origin/v1..v1  # from origin/v1 to the head of v1<br>
<br>
For every branch that has an upstream remote-tracking branch git<br>
maintains an alias @{upstream} (short version @{u}), so the commands<br>
above can be given as::<br>
<br>
  Â  $ git log @{u}..<br>
  Â  $ git log v1@{u}..v1<br>
<br>
To see the status of all branches::<br>
<br>
  Â  $ git branch -avv<br>
<br>
To compare the status of local branches with a remote repo::<br>
<br>
  Â  $ git remote show origin<br>
<br>
Read `how to recover from upstream rebase<br>
<<a href="https://git-scm.com/docs/git-rebase#_recovering_from_upstream_rebase" rel="noreferrer" target="_blank">https://git-scm.com/docs/git-rebase#_recovering_from_upstream_rebase</a>>`_.<br>
It is in ``git help rebase``.<br>
<br>
On the other hand don't be too afraid about commit editing. You can<br>
safely edit, reorder, remove, combine and split commits that haven't<br>
been pushed yet. You can even push commits to your own (backup) repo,<br>
edit them later and force-push edited commits to replace what have<br>
already been pushed. Not a problem until commits are in a public<br>
or shared repository.<br>
<br>
<br>
Undo<br>
====<br>
<br>
Whatever you do, don't panic. Almost anything in git can be undone.<br>
<br>
<br>
git checkout: restore file's content<br>
------------------------------------<br>
<br>
``git checkout``, for example, can be used to restore the content of<br>
file(s) to that one of a commit. Like this::<br>
<br>
  Â  git checkout HEAD~ README<br>
<br>
The commands restores the contents of README file to the last but one<br>
commit in the current branch. By default the commit ID is simply HEAD;<br>
i.e. ``git checkout README`` restores README to the latest commit.<br>
<br>
(Do not use ``git checkout`` to view a content of a file in a commit,<br>
use ``git cat-file -p``; e.g. ``git cat-file -p HEAD~:path/to/README``).<br>
<br>
<br>
git reset: remove (non-pushed) commits<br>
--------------------------------------<br>
<br>
``git reset`` moves the head of the current branch. The head can be<br>
moved to point to any commit but it's often used to remove a commit or<br>
a few (preferably, non-pushed ones) from the top of the branch - that<br>
is, to move the branch backward in order to undo a few (non-pushed)<br>
commits.<br>
<br>
``git reset`` has three modes of operation - soft, hard and mixed.<br>
Default is mixed. ProGit `explains<br>
<<a href="https://git-scm.com/book/en/Git-Tools-Reset-Demystified" rel="noreferrer" target="_blank">https://git-scm.com/book/en/Git-Tools-Reset-Demystified</a>>`_ the<br>
difference very clearly. Bare repositories don't have indices or<br>
working trees so in a bare repo only soft reset is possible.<br>
<br>
<br>
Unstaging<br>
'''''''''<br>
<br>
Mixed mode reset with a path or paths can be used to unstage changes -<br>
that is, to remove from index changes added with ``git add`` for<br>
committing. See `The Book<br>
<<a href="https://git-scm.com/book/en/Git-Basics-Undoing-Things" rel="noreferrer" target="_blank">https://git-scm.com/book/en/Git-Basics-Undoing-Things</a>>`_ for details<br>
about unstaging and other undo tricks.<br>
<br>
<br>
git reflog: reference log<br>
-------------------------<br>
<br>
Removing commits with ``git reset`` or moving the head of a branch<br>
sounds dangerous and it is. But there is a way to undo: another<br>
reset back to the original commit. Git doesn't remove commits<br>
immediately; unreferenced commits (in git terminology they are called<br>
"dangling commits") stay in the database for some time (default is two<br>
weeks) so you can reset back to it or create a new branch pointing to<br>
the original commit.<br>
<br>
For every move of a branch's head - with ``git commit``, ``git<br>
checkout``, ``git fetch``, ``git pull``, ``git rebase``, ``git reset``<br>
and so on - git stores a reference log (reflog for short). For every<br>
move git stores where the head was. Command ``git reflog`` can be used<br>
to view (and manipulate) the log.<br>
<br>
In addition to the moves of the head of every branch git stores the<br>
moves of the HEAD - a symbolic reference that (usually) names the<br>
current branch. HEAD is changed with ``git checkout $BRANCH``.<br>
<br>
By default ``git reflog`` shows the moves of the HEAD, i.e. the<br>
command is equivalent to ``git reflog HEAD``. To show the moves of the<br>
head of a branch use the command ``git reflog $BRANCH``.<br>
<br>
So to undo a ``git reset`` lookup the original commit in ``git<br>
reflog``, verify it with ``git show`` or ``git log`` and run ``git<br>
reset $COMMIT_ID``. Git stores the move of the branch's head in<br>
reflog, so you can undo that undo later again.<br>
<br>
In a more complex situation you'd want to move some commits along with<br>
resetting the head of the branch. Cherry-pick them to the new branch.<br>
For example, if you want to reset the branch ``master`` back to the<br>
original commit but preserve two commits created in the current branch<br>
do something like::<br>
<br>
  Â  $ git branch save-master # create a new branch saving master<br>
  Â  $ git reflog # find the original place of master<br>
  Â  $ git reset $COMMIT_ID<br>
  Â  $ git cherry-pick save-master~ save-master<br>
  Â  $ git branch -D save-master # remove temporary branch<br>
<br>
<br>
git revert: revert a commit<br>
---------------------------<br>
<br>
``git revert`` reverts a commit or commits, that is, it creates a new<br>
commit or commits that revert(s) the effects of the given commits.<br>
It's the only way to undo published commits (``git commit --amend``,<br>
``git rebase`` and ``git reset`` change the branch in<br>
non-fast-forwardable ways so they should only be used for non-pushed<br>
commits.)<br>
<br>
There is a problem with reverting a merge commit. ``git revert`` can<br>
undo the code created by the merge commit but it cannot undo the fact<br>
of merge. See the discussion `How to revert a faulty merge<br>
<<a href="https://www.kernel.org/pub/software/scm/git/docs/howto/revert-a-faulty-merge.html" rel="noreferrer" target="_blank">https://www.kernel.org/pub/software/scm/git/docs/howto/revert-a-faulty-merge.html</a>>`_.<br>
<br>
<br>
One thing that cannot be undone<br>
-------------------------------<br>
<br>
Whatever you undo, there is one thing that cannot be undone -<br>
overwritten uncommitted changes. Uncommitted changes don't belong to<br>
git so git cannot help preserving them.<br>
<br>
Most of the time git warns you when you're going to execute a command<br>
that overwrites uncommitted changes. Git doesn't allow you to switch<br>
branches with ``git checkout``. It stops you when you're going to<br>
rebase with non-clean working tree. It refuses to pull new commits<br>
over non-committed files.<br>
<br>
But there are commands that do exactly that - overwrite files in the<br>
working tree. Commands like ``git checkout $PATHs`` or ``git reset<br>
--hard`` silently overwrite files including your uncommitted changes.<br>
<br>
With that in mind you can understand the stance "commit early, commit<br>
often". Commit as often as possible. Commit on every save in your<br>
editor or IDE. You can edit your commits before pushing - edit commit<br>
messages, change commits, reorder, combine, split, remove. But save<br>
your changes in git database, either commit changes or at least stash<br>
them with ``git stash``.<br>
<br>
<br>
Merge or rebase?<br>
================<br>
<br>
Internet is full of heated discussions on the topic: "merge or<br>
rebase?" Most of them are meaningless. When a DVCS is being used in a<br>
big team with a big and complex project with many branches there is<br>
simply no way to avoid merges. So the question's diminished to<br>
"whether to use rebase, and if yes - when to use rebase?" Considering<br>
that it is very much recommended not to rebase published commits the<br>
question's diminished even further: "whether to use rebase on<br>
non-pushed commits?"<br>
<br>
That small question is for the team to decide. The author of the PEP<br>
recommends to use rebase when pulling, i.e. always do ``git pull<br>
--rebase`` or even configure automatic setup of rebase for every new<br>
branch::<br>
<br>
  Â  $ git config branch.autosetuprebase always<br>
<br>
and configure rebase for existing branches::<br>
<br>
  Â  $ git config branch.$NAME.rebase true<br>
<br>
For example::<br>
<br>
  Â  $ git config branch.v1.rebase true<br>
  Â  $ git config branch.master.rebase true<br>
<br>
After that ``git pull origin master`` becomes equivalent to ``git pull<br>
--rebase origin master``.<br>
<br>
It is recommended to create new commits in a separate feature or topic<br>
branch while using rebase to update the mainline branch. When the<br>
topic branch is ready merge it into mainline. To avoid a tedious task<br>
of resolving large number of conflicts at once you can merge the topic<br>
branch to the mainline from time to time and switch back to the topic<br>
branch to continue working on it. The entire workflow would be<br>
something like::<br>
<br>
  Â  $ git checkout -b issue-42  # create a new issue branch and switch to it<br>
  Â  Â  Â  ...edit/test/commit...<br>
  Â  $ git checkout master<br>
  Â  $ git pull --rebase origin master  # update master from the upstream<br>
  Â  $ git merge issue-42<br>
  Â  $ git branch -d issue-42  # delete the topic branch<br>
  Â  $ git push origin master<br>
<br>
When the topic branch is deleted only the label is removed, commits<br>
are stayed in the database, they are now merged into master::<br>
<br>
  Â  o--o--o--o--o--M--< master - the mainline branch<br>
  Â  Â  Â  \  Â  Â  Â  Â /<br>
  Â  Â  Â  Â --*--*--*  Â  Â  Â  Â  Â  Â - the topic branch, now unnamed<br>
<br>
The topic branch is deleted to avoid cluttering branch namespace with<br>
small topic branches. Information on what issue was fixed or what<br>
feature was implemented should be in the commit messages.<br>
<br>
<br>
Null-merges<br>
===========<br>
<br>
Git has a builtin merge strategy for what Python core developers call<br>
"null-merge"::<br>
<br>
  Â  $ git merge -s ours v1  # null-merge v1 into master<br>
<br>
<br>
Advanced configuration<br>
======================<br>
<br>
Line endings<br>
------------<br>
<br>
Git has builtin mechanisms to handle line endings between platforms<br>
with different end-of-line styles. To allow git to do CRLF conversion<br>
assign ``text`` attribute to files using `.gitattributes<br>
<<a href="https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html" rel="noreferrer" target="_blank">https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html</a>>`_.<br>
For files that have to have specific line endings assign ``eol``<br>
attribute. For binary files the attribute is, naturally, ``binary``.<br>
<br>
For example::<br>
<br>
  Â  $ cat .gitattributes<br>
  Â  *.py text<br>
  Â  *.txt text<br>
  Â  *.png binary<br>
  Â  /readme.txt eol=CRLF<br>
<br>
To check what attributes git uses for files use ``git check-attr``<br>
command. For example::<br>
<br>
$ git check-attr -a -- \*.py<br>
<br>
<br>
Advanced topics<br>
===============<br>
<br>
Staging area<br>
------------<br>
<br>
Staging area aka index aka cache is a distinguishing feature of git.<br>
Staging area is where git collects patches before committing them.<br>
Separation between collecting patches and commit phases provides a<br>
very useful feature of git: you can review collected patches before<br>
commit and even edit them - remove some hunks, add new hunks and<br>
review again.<br>
<br>
To add files to the index use ``git add``. Collecting patches before<br>
committing means you need to do that for every change, not only to add<br>
new (untracked) files. To simplify committing in case you just want to<br>
commit everything without reviewing run ``git commit --all`` (or just<br>
``-a``) - the command adds every changed tracked file to the index and<br>
then commit. To commit a file or files regardless of patches collected<br>
in the index run ``git commit [--only|-o] -- $FILE...``.<br>
<br>
To add hunks of patches to the index use ``git add --patch`` (or just<br>
``-p``). To remove collected files from the index use ``git reset HEAD<br>
-- $FILE...`` To add/inspect/remove collected hunks use ``git add<br>
--interactive`` (``-i``).<br>
<br>
To see the diff between the index and the last commit (i.e., collected<br>
patches) use ``git diff --cached``. To see the diff between the<br>
working tree and the index (i.e., uncollected patches) use just ``git<br>
diff``. To see the diff between the working tree and the last commit<br>
(i.e., both collected and uncollected patches) run ``git diff HEAD``.<br>
<br>
See `WhatIsTheIndex<br>
<<a href="https://git.wiki.kernel.org/index.php/WhatIsTheIndex" rel="noreferrer" target="_blank">https://git.wiki.kernel.org/index.php/WhatIsTheIndex</a>>`_ and<br>
`IndexCommandQuickref<br>
<<a href="https://git.wiki.kernel.org/index.php/IndexCommandQuickref" rel="noreferrer" target="_blank">https://git.wiki.kernel.org/index.php/IndexCommandQuickref</a>>`_ in Git<br>
Wiki.<br>
<br>
<br>
ReReRe<br>
======<br>
<br>
Rerere is a mechanism that helps to resolve repeated merge conflicts.<br>
The most frequent source of recurring merge conflicts are topic<br>
branches that are merged into mainline and then the merge commits are<br>
removed; that's often performed to test the topic branches and train<br>
rerere; merge commits are removed to have clean linear history and<br>
finish the topic branch with only one last merge commit.<br>
<br>
Rerere works by remembering the states of tree before and after a<br>
successful commit. That way rerere can automatically resolve conflicts<br>
if they appear in the same files.<br>
<br>
Rerere can be used manually with ``git rerere`` command but most often<br>
it's used automatically. Enable rerere with these commands in a<br>
working tree::<br>
<br>
  Â  $ git config rerere.enabled true<br>
  Â  $ git config rerere.autoupdate true<br>
<br>
You don't need to turn rerere on globally - you don't want rerere in<br>
bare repositories or single-branche repositories; you only need rerere<br>
in repos where you often perform merges and resolve merge conflicts.<br>
<br>
See `Rerere <<a href="https://git-scm.com/book/en/Git-Tools-Rerere" rel="noreferrer" target="_blank">https://git-scm.com/book/en/Git-Tools-Rerere</a>>`_ in The<br>
Book.<br>
<br>
<br>
Database maintenance<br>
====================<br>
<br>
Git object database and other files/directories under ``.git`` require<br>
periodic maintenance and cleanup. For example, commit editing left<br>
unreferenced objects (dangling objects, in git terminology) and these<br>
objects should be pruned to avoid collecting cruft in the DB. The<br>
command ``git gc`` is used for maintenance. Git automatically runs<br>
``git gc --auto`` as a part of some commands to do quick maintenance.<br>
Users are recommended to run ``git gc --aggressive`` from time to<br>
time; ``git help gc`` recommends to run it  every few hundred<br>
changesets; for more intensive projects it should be something like<br>
once a week and less frequently (biweekly or monthly) for lesser<br>
active projects.<br>
<br>
``git gc --aggressive`` not only removes dangling objects, it also<br>
repacks object database into indexed and better optimized pack(s); it<br>
also packs symbolic references (branches and tags). Another way to do<br>
it is to run ``git repack``.<br>
<br>
There is a well-known `message<br>
<<a href="https://gcc.gnu.org/ml/gcc/2007-12/msg00165.html" rel="noreferrer" target="_blank">https://gcc.gnu.org/ml/gcc/2007-12/msg00165.html</a>>`_ from Linus<br>
Torvalds regarding "stupidity" of ``git gc --aggressive``. The message<br>
can safely be ignored now. It is old and outdated, ``git gc<br>
--aggressive`` became much better since that time.<br>
<br>
For those who still prefer ``git repack`` over ``git gc --aggressive``<br>
the recommended parameters are ``git repack -a -d -f --depth=20<br>
--window=250``. See `this detailed experiment<br>
<<a href="http://vcscompare.blogspot.ru/2008/06/git-repack-parameters.html" rel="noreferrer" target="_blank">http://vcscompare.blogspot.ru/2008/06/git-repack-parameters.html</a>>`_<br>
for explanation of the effects of these parameters.<br>
<br>
>From time to time run ``git fsck [--strict]`` to verify integrity of<br>
the database. ``git fsck`` may produce a list of dangling objects;<br>
that's not an error, just a reminder to perform regular maintenance.<br>
<br>
<br>
Tips and tricks<br>
===============<br>
<br>
Command-line options and arguments<br>
----------------------------------<br>
<br>
`git help cli<br>
<<a href="https://www.kernel.org/pub/software/scm/git/docs/gitcli.html" rel="noreferrer" target="_blank">https://www.kernel.org/pub/software/scm/git/docs/gitcli.html</a>>`_<br>
recommends not to combine short options/flags. Most of the times<br>
combining works: ``git commit -av`` works perfectly, but there are<br>
situations when it doesn't. E.g., ``git log -p -5`` cannot be combined<br>
as ``git log -p5``.<br>
<br>
Some options have arguments, some even have default arguments. In that<br>
case the argument for such option must be spelled in a sticky way:<br>
``-Oarg``, never ``-O arg`` because for an option that has a default<br>
argument the latter means "use default value for option ``-O`` and<br>
pass ``arg`` further to the option parser". For example, ``git grep``<br>
has an option ``-O`` that passes a list of names of the found files to<br>
a program; default program for ``-O`` is a pager (usually ``less``),<br>
but you can use your editor::<br>
<br>
  Â  $ git grep -Ovim # but not -O vim<br>
<br>
BTW, if git is instructed to use ``less`` as the pager (i.e., if pager<br>
is not configured in git at all it uses ``less`` by default, or if it<br>
gets ``less`` from GIT_PAGER or PAGER environment variables, or if it<br>
was configured with ``git config --global core.pager less``, or<br>
``less`` is used in the command ``git grep -Oless``) ``git grep``<br>
passes ``+/$pattern`` option to ``less`` which is quite convenient.<br>
Unfortunately, ``git grep`` doesn't pass the pattern if the pager is<br>
not exactly ``less``, even if it's ``less`` with parameters (something<br>
like ``git config --global core.pager less -FRSXgimq``); fortunately,<br>
``git grep -Oless`` always passes the pattern.<br>
<br>
<br>
bash/zsh completion<br>
-------------------<br>
<br>
It's a bit hard to type ``git rebase --interactive --preserve-merges<br>
HEAD~5`` manually even for those who are happy to use command-line,<br>
and this is where shell completion is of great help. Bash/zsh come<br>
with programmable completion, often automatically installed and<br>
enabled, so if you have bash/zsh and git installed, chances are you<br>
are already done - just go and use it at the command-line.<br>
<br>
If you don't have necessary bits installed, install and enable<br>
bash_completion package. If you want to upgrade your git completion to<br>
the latest and greatest download necessary file from `git contrib<br>
<<a href="https://git.kernel.org/cgit/git/git.git/tree/contrib/completion" rel="noreferrer" target="_blank">https://git.kernel.org/cgit/git/git.git/tree/contrib/completion</a>>`_.<br>
<br>
Git-for-windows comes with git-bash for which bash completion is<br>
installed and enabled.<br>
<br>
<br>
bash/zsh prompt<br>
---------------<br>
<br>
For command-line lovers shell prompt can carry a lot of useful<br>
information. To include git information in the prompt use<br>
`git-prompt.sh<br>
<<a href="https://git.kernel.org/cgit/git/git.git/tree/contrib/completion/git-prompt.sh" rel="noreferrer" target="_blank">https://git.kernel.org/cgit/git/git.git/tree/contrib/completion/git-prompt.sh</a>>`_.<br>
Read the detailed instructions in the file.<br>
<br>
Search the Net for "git prompt" to find other prompt variants.<br>
<br>
<br>
git on server<br>
=============<br>
<br>
The simplest way to publish a repository or a group of repositories is<br>
``git daemon``. The daemon provides anonymous access, by default it is<br>
read-only. The repositories are accessible by git protocol (git://<br>
URLs). Write access can be enabled but the protocol lacks any<br>
authentication means, so it should be enabled only within a trusted<br>
LAN. See ``git help daemon`` for details.<br>
<br>
Git over ssh provides authentication and repo-level authorisation as<br>
repositories can be made user- or group-writeable (see parameter<br>
``core.sharedRepository`` in ``git help config``). If that's too<br>
permissive or too restrictive for some project's needs there is a<br>
wrapper `gitolite <<a href="http://gitolite.com/gitolite/index.html" rel="noreferrer" target="_blank">http://gitolite.com/gitolite/index.html</a>>`_ that can<br>
be configured to allow access with great granularity; gitolite is<br>
written in Perl and has a lot of documentation.<br>
<br>
Web interface to browse repositories can be created using `gitweb<br>
<<a href="https://git.kernel.org/cgit/git/git.git/tree/gitweb" rel="noreferrer" target="_blank">https://git.kernel.org/cgit/git/git.git/tree/gitweb</a>>`_ or `cgit<br>
<<a href="http://git.zx2c4.com/cgit/about/" rel="noreferrer" target="_blank">http://git.zx2c4.com/cgit/about/</a>>`_. Both are CGI scripts (written in<br>
Perl and C). In addition to web interface both provide read-only dumb<br>
http access for git (http(s):// URLs).<br>
<br>
There are also more advanced web-based development environments that<br>
include ability to manage users, groups and projects; private,<br>
group-accessible and public repositories; they often include issue<br>
trackers, wiki pages, pull requests and other tools for development<br>
and communication. Among these environments are `Kallithea<br>
<<a href="https://kallithea-scm.org/" rel="noreferrer" target="_blank">https://kallithea-scm.org/</a>>`_ and `pagure <<a href="https://pagure.io/" rel="noreferrer" target="_blank">https://pagure.io/</a>>`_,<br>
both are written in Python; pagure was written by Fedora developers<br>
and is being used to develop some Fedora projects. `Gogs<br>
<<a href="http://gogs.io/" rel="noreferrer" target="_blank">http://gogs.io/</a>>`_ is written in Go; there is a fork `Gitea<br>
<<a href="http://gitea.io/" rel="noreferrer" target="_blank">http://gitea.io/</a>>`_.<br>
<br>
And last but not least, `Gitlab <<a href="https://about.gitlab.com/" rel="noreferrer" target="_blank">https://about.gitlab.com/</a>>`_. It's<br>
perhaps the most advanced web-based development environment for git.<br>
Written in Ruby, community edition is free and open source (MIT<br>
license).<br>
<br>
<br>
>From Mercurial to git<br>
=====================<br>
<br>
There are many tools to convert Mercurial repositories to git. The<br>
most famous are, probably, `hg-git <<a href="https://hg-git.github.io/" rel="noreferrer" target="_blank">https://hg-git.github.io/</a>>`_ and<br>
`fast-export <<a href="http://repo.or.cz/w/fast-export.git" rel="noreferrer" target="_blank">http://repo.or.cz/w/fast-export.git</a>>`_ (many years ago<br>
it was known under the name ``hg2git``).<br>
<br>
But a better tool, perhaps the best, is `git-remote-hg<br>
<<a href="https://github.com/felipec/git-remote-hg" rel="noreferrer" target="_blank">https://github.com/felipec/git-remote-hg</a>>`_. It provides transparent<br>
bidirectional (pull and push) access to Mercurial repositories from<br>
git. Its author wrote a `comparison of alternatives<br>
<<a href="https://github.com/felipec/git/wiki/Comparison-of-git-remote-hg-alternatives" rel="noreferrer" target="_blank">https://github.com/felipec/git/wiki/Comparison-of-git-remote-hg-alternatives</a>>`_<br>
that seems to be mostly objective.<br>
<br>
To use git-remote-hg, install or clone it, add to your PATH (or copy<br>
script ``git-remote-hg`` to a directory that's already in PATH) and<br>
prepend ``hg::`` to Mercurial URLs. For example::<br>
<br>
  Â  $ git clone <a href="https://github.com/felipec/git-remote-hg.git" rel="noreferrer" target="_blank">https://github.com/felipec/git-remote-hg.git</a><br>
  Â  $ PATH=$PATH:"`pwd`"/git-remote-hg<br>
  Â  $ git clone hg::<a href="https://hg.python.org/peps/" rel="noreferrer" target="_blank">https://hg.python.org/peps/</a> PEPs<br>
<br>
To work with the repository just use regular git commands including<br>
``git fetch/pull/push``.<br>
<br>
To start converting your Mercurial habits to git see the page<br>
`Mercurial for Git users<br>
<<a href="https://mercurial.selenic.com/wiki/GitConcepts" rel="noreferrer" target="_blank">https://mercurial.selenic.com/wiki/GitConcepts</a>>`_ at Mercurial wiki.<br>
At the second half of the page there is a table that lists<br>
corresponding Mercurial and git commands. Should work perfectly in<br>
both directions.<br>
<br>
<br>
Copyright<br>
=========<br>
<br>
This document has been placed in the public domain.<br>
<br>
<br>
<br>
..<br>
  Â Local Variables:<br>
  Â mode: indented-text<br>
  Â indent-tabs-mode: nil<br>
  Â sentence-end-double-space: t<br>
  Â fill-column: 70<br>
  Â coding: utf-8<br>
  Â End:<br>
  Â vim: set fenc=us-ascii tw=70 :<br>
_______________________________________________<br>
Python-Dev mailing list<br>
<a href="mailto:Python-Dev@python.org" target="_blank">Python-Dev@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/python-dev" rel="noreferrer" target="_blank">https://mail.python.org/mailman/listinfo/python-dev</a><br>
Unsubscribe: <a href="https://mail.python.org/mailman/options/python-dev/brett%40python.org" rel="noreferrer" target="_blank">https://mail.python.org/mailman/options/python-dev/brett%40python.org</a><br>
</blockquote></div>

RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4