X-Git-Url: https://git.phdru.name/?a=blobdiff_plain;f=pep-git.txt;h=8ef719d2ba83a54cb7fe2b72e3731463f87ece50;hb=e9e7f5a63ac0b7c94f1bb3db7ef0d04921683129;hp=402dac8907b5731166e4ae04ba822737a5d08808;hpb=d97d98eb25a34050380fa73f58752c2e2af5c207;p=git-wiki.git diff --git a/pep-git.txt b/pep-git.txt index 402dac8..8ef719d 100644 --- a/pep-git.txt +++ b/pep-git.txt @@ -199,9 +199,9 @@ 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 and leaves the id -(the hash) of the head commit in file .git/FETCH_HEAD and updates -remote-tracking branch. +$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 @@ -326,6 +326,11 @@ 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 +`_ +for caveats; in 2.4 the push-to-deploy feature was `further improved +`_. + Tags '''' @@ -338,11 +343,11 @@ explicitly:: For example:: - $ git fetch origin tag 1.4.2 tag 2.1.7 + $ 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 (lightweight tags are also private for a repo, they cannot be -pushed). To push tags list them explicitly:: +tags. To push tags list them explicitly:: $ git push origin tag 1.4.2 $ git push origin v1 v2 tag 2.1.7 @@ -386,9 +391,9 @@ Read `how to recover 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, remove, reorder, combine and split commits that hasn't +safely edit, remove, reorder, 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 has +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. @@ -440,16 +445,82 @@ 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 ``v2`` back to the +original commit but preserve two commits created in the current branch +do something like:: + + $ git branch save-v2 # create a new branch saving v2 + $ git reflog # find the original place of v2 + $ git reset $COMMIT_ID + $ git cherry-pick save-v2~ save-v2 + $ git branch -D save-v2 # remove temporary branch + git revert: revert a commit --------------------------- -How to undo a merge -https://www.kernel.org/pub/software/scm/git/docs/howto/revert-a-faulty-merge.html +``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 +`_. One thing that cannot be undone ------------------------------- -"Commit early, commit often". +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 warns you when you try to +switch branches with ``git checkout``. It warns 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 - change, +reorder, combine, remove. But save your changes in git database, +either commit changes or at least stash them with ``git stash``. Merge or rebase? @@ -520,10 +591,31 @@ Git has a builtin merge strategy for what Python core developers call $ git merge -s ours v1 # null-merge v1 into v2 -ReReRe -====== +Advanced configuration +====================== -https://git-scm.com/book/en/Git-Tools-Rerere +Line endings +------------ + +Git has builtin mechanisms to handle line endings between platforms +with different EOL styles. To allow git to do CRLF conversion assign +``text`` attribute to files using `.gitattributes +`_. +For files that have to have specific line ending 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 @@ -540,15 +632,10 @@ Staging area aka index is a distinguishing feature of git. See Wiki. -Advanced configuration -====================== - -Line endings ------------- - -Git has builtin mechanisms to handle line endings. +ReReRe +====== -TODO: describe crlf configuration and .gitattributes. +https://git-scm.com/book/en/Git-Tools-Rerere Database maintenance