many minor edits in ru/*.txt
[gitmagic/gitmagic.git] / en / grandmaster.txt
blob55e9eb949f63d8ddce6cca1fce4d4c84dc289b4b
1 == Git Grandmastery ==
3 By now, you should be able to navigate the *git help* pages and understand
4 almost everything. However, pinpointing the exact command required to solve a
5 given problem can be tedious. Perhaps I can save you some time: below are some
6 recipes I have needed in the past.
8 === Source Releases ===
10 For my projects, Git tracks exactly the files I'd like to archive and release
11 to users. To create a tarball of the source code, I run:
13  $ git archive --format=tar --prefix=proj-1.2.3/ HEAD
15 === Commit What Changed ===
17 Telling Git when you've added, deleted and renamed files is troublesome for
18 certain projects. Instead, you can type:
20  $ git add .
21  $ git add -u
23 Git will look at the files in the current directory and work out the details by
24 itself. Instead of the second add command, run `git commit -a` if you also
25 intend to commit at this time. See *git help ignore* for how to specify files
26 that should be ignored.
28 You can perform the above in a single pass with:
30  $ git ls-files -d -m -o -z | xargs -0 git update-index --add --remove
32 The *-z* and *-0* options prevent ill side-effects from filenames containing
33 strange characters. As this command adds ignored files, you may want to use the
34 `-x` or `-X` option.
36 === My Commit Is Too Big! ===
38 Have you neglected to commit for too long? Been coding furiously and forgotten
39 about source control until now? Made a series of unrelated changes, because
40 that's your style?
42 No worries. Run:
44  $ git add -p
46 For each edit you made, Git will show you the hunk of code that was changed,
47 and ask if it should be part of the next commit. Answer with "y" or "n". You
48 have other options, such as postponing the decision; type "?" to learn more.
50 Once you're satisfied, type
52  $ git commit
54 to commit precisely the changes you selected (the 'staged' changes). Make sure
55 you omit the *-a* option, otherwise Git will commit all the edits.
57 What if you've edited many files in many places? Reviewing each change one by
58 one becomes frustratingly mind-numbing. In this case, use *git add -i*, whose
59 interface is less straightforward, but more flexible. With a few keystrokes,
60 you can stage or unstage several files at a time, or review and select changes
61 in particular files only. Alternatively, run *git commit \--interactive* which
62 automatically commits after you're done.
64 === The Index: Git's Staging Area ===
66 So far we have avoided Git's famous 'index', but we must now confront it to
67 explain the above. The index is a temporary staging area. Git seldom shuttles
68 data directly between your project and its history. Rather, Git first writes
69 data to the index, and then copies the data in the index to its final
70 destination.
72 For example, *commit -a* is really a two-step process. The first step places a
73 snapshot of the current state of every tracked file into the index. The second
74 step permanently records the snapshot now in the index. Committing without the
75 *-a* option only performs the second step, and only makes sense after running
76 commands that somehow change the index, such as *git add*.
78 Usually we can ignore the index and pretend we are reading straight from and writing straight to the history. On this occasion, we want finer control, so we manipulate the index. We place a snapshot of some, but not all, of our changes into the index, and then permanently record this carefully rigged snapshot.
80 === Don't Lose Your HEAD ===
82 The HEAD tag is like a cursor that normally points at the latest commit, advancing with each new commit. Some Git commands let you move it. For example:
84  $ git reset HEAD~3
86 will move the HEAD three commits back. Thus all Git commands now act as if you hadn't made those last three commits, while your files remain in the present. See the help page for some applications.
88 But how can you go back to the future? The past commits know nothing of the future.
90 If you have the SHA1 of the original HEAD then:
92  $ git reset 1b6d
94 But suppose you never took it down? Don't worry: for commands like these, Git saves the original HEAD as a tag called ORIG_HEAD, and you can return safe and sound with:
96  $ git reset ORIG_HEAD
98 === HEAD-hunting ===
100 Perhaps ORIG_HEAD isn't enough. Perhaps you've just realized you made a monumental mistake and you need to go back to an ancient commit in a long-forgotten branch.
102 By default, Git keeps a commit for at least two weeks, even if you ordered
103 Git to destroy the branch containing it. The trouble is finding the appropriate
104 hash. You could look at all the hash values in `.git/objects` and use trial
105 and error to find the one you want. But there's a much easier way.
107 Git records every hash of a commit it computes in `.git/logs`. The subdirectory `refs` contains the history of all activity on all branches, while the file `HEAD` shows every hash value it has ever taken. The latter can be used to find hashes of commits on branches that have been accidentally lopped off.
109 The reflog command provides a friendly interface to these log files. Try
111   $ git reflog
113 Instead of cutting and pasting hashes from the reflog, try:
115  $ git checkout "@{10 minutes ago}"
117 Or checkout the 5th-last visited commit via:
119  $ git checkout "@{5}"
121 See the ``Specifying Revisions'' section of *git help rev-parse* for more.
123 You may wish to configure a longer grace period for doomed commits. For
124 example:
126   $ git config gc.pruneexpire "30 days"
128 means a deleted commit will only be permanently lost once 30 days have passed
129 and *git gc* is run.
131 You may also wish to disable automatic invocations of *git gc*:
133   $ git config gc.auto 0
135 in which case commits will only be deleted when you run *git gc* manually.
137 === Building On Git ===
139 In true UNIX fashion, Git's design allows it to be easily used as a low-level component of other programs, such as GUI and web interfaces, alternative command-line interfaces, patch managements tools, importing and conversion tools and so on. In fact, some Git commands are themselves scripts standing on the shoulders of giants. With a little tinkering, you can customize Git to suit your preferences.
141 One easy trick is to use built-in Git aliases to shorten your most frequently
142 used commands:
144   $ git config --global alias.co checkout
145   $ git config --global --get-regexp alias  # display current aliases
146   alias.co checkout
147   $ git co foo                              # same as 'git checkout foo'
149 Another is to print the current branch in the prompt, or window title.
150 Invoking
152   $ git symbolic-ref HEAD
154 shows the current branch name. In practice, you most likely want to remove
155 the "refs/heads/" and ignore errors:
157   $ git symbolic-ref HEAD 2> /dev/null | cut -b 12-
159 The +contrib+ subdirectory is a treasure trove of tools built on Git.
160 In time, some of them may be promoted to official commands. On Debian and
161 Ubuntu, this directory lives at +/usr/share/doc/git-core/contrib+.
163 One popular resident is +workdir/git-new-workdir+. Via clever symlinking, this script creates a new working directory whose history is shared with the original repository:
165   $ git-new-workdir an/existing/repo new/directory
167 The new directory and the files within can be thought of as a clone, except since the history is shared, the two trees automatically stay in sync. There's no need to merge, push or pull.
169 === Daring Stunts ===
171 These days, Git makes it difficult for the user to accidentally destroy data.
172 But if you know what you are doing, you can override safeguards for common
173 commands.
175 *Checkout*: Uncommitted changes cause checkout to fail. To destroy your changes, and checkout a given commit anyway, use the force flag:
177   $ git checkout -f HEAD^
179 On the other hand, if you specify particular paths for checkout, then there are no safety checks. The supplied paths are quietly overwritten. Take care if you use checkout in this manner.
181 *Reset*: Reset also fails in the presence of uncommitted changes. To force it through, run:
183   $ git reset --hard 1b6d
185 *Branch*: Deleting branches fails if this causes changes to be lost. To force a deletion, type:
187   $ git branch -D dead_branch  # instead of -d
189 Similarly, attempting to overwrite a branch via a move fails if data loss would ensue. To force a branch move, type:
191   $ git branch -M source target  # instead of -m
193 Unlike checkout and reset, these two commands defer data destruction. The
194 changes are still stored in the .git subdirectory, and can be retrieved by
195 recovering the appropriate hash from `.git/logs` (see "HEAD-hunting" above).
196 By default, they will be kept for at least two weeks.
198 *Clean*: Some git commands refuse to proceed because they're worried about
199 clobbering untracked files. If you're certain that all untracked files and
200 directories are expendable, then delete them mercilessly with:
202   $ git clean -f -d
204 Next time, that pesky command will work!
206 === Preventing Bad Commits ===
208 Stupid mistakes abound in the histories of many of my projects. The most
209 frightening are missing files due to a forgotten *git add*. Luckily I
210 have yet to lose crucial data though accidental omission because I rarely
211 delete original working directories. I typically notice the error a few commits
212 later, so the only damage is a bit of missing history and a sheepish admission
213 of guilt.
215 I also regularly commit (literally and git-erally) the lesser transgression of
216 trailing whitespace. Though harmless, I wish these also never appeared on the
217 public record.
219 In addition, though unscathed so far, I worry about leaving merge conflicts
220 unresolved. Usually I catch them when I build a project, but there are some
221 cases this can overlook.
223 If only I had bought idiot insurance by using a _hook_ to alert me about these
224 problems:
226  $ cd .git/hooks
227  $ cp pre-commit.sample pre-commit  # Older Git versions: chmod +x pre-commit
229 Now Git aborts a commit if useless whitespace or unresolved merge conflicts are
230 detected.
232 For this guide, I eventually added the following to the beginning of the
233 *pre-commit* hook to guard against absent-mindedness:
235  if git ls-files -o | grep '\.txt$'; then
236    echo FAIL! Untracked .txt files.
237    exit 1
238  fi
240 Several git operations support hooks; see *git help hooks*. One can write hooks
241 to complain about spelling mistakes in commit messages, add new files, indent
242 paragraphs, append an entry to a webpage, play a sound, and so on.
244 We activated the sample *post-update* hook earlier when discussing Git over
245 HTTP; this causes Git to run this script whenever the head has moved. The
246 sample post-update script updates a few files Git needs for communication over
247 Git-agnostic transports such as HTTP.