Converted most subsections to sections.
[gitmagic.git] / en / grandmaster.txt
blob33cc743e300ee3a29247df9f895a598270d7b8c0
1 == Git Grandmastery ==
3 This pretentiously named page is my dumping ground for uncategorized Git tricks.
5 === Source Releases ===
7 For my projects, Git tracks exactly the files I'd like to archive and release
8 to users. To create a tarball of the source code, I run:
10  $ git archive --format=tar --prefix=proj-1.2.3/ HEAD
12 === Commit What Changed ===
14 Telling Git when you've added, deleted and renamed files is troublesome for
15 certain projects. Instead, you can type:
17  $ git add .
18  $ git add -u
20 Git will look at the files in the current directory and work out the details by
21 itself. Instead of the second add command, run `git commit -a` if you also
22 intend to commit at this time. See *git help ignore* for how to specify files
23 that should be ignored.
25 You can perform the above in a single pass with:
27  $ git ls-files -d -m -o -z | xargs -0 git update-index --add --remove
29 The *-z* and *-0* options prevent ill side-effects from filenames containing
30 strange characters. As this command adds ignored files, you may want to use the
31 `-x` or `-X` option.
33 === My Commit Is Too Big! ===
35 Have you neglected to commit for too long? Been coding furiously and forgotten
36 about source control until now? Made a series of unrelated changes, because
37 that's your style?
39 No worries. Run:
41  $ git add -p
43 For each edit you made, Git will show you the hunk of code that was changed,
44 and ask if it should be part of the next commit. Answer with "y" or "n". You
45 have other options, such as postponing the decision; type "?" to learn more.
47 Once you're satisfied, type
49  $ git commit
51 to commit precisely the changes you selected (the 'staged' changes). Make sure
52 you omit the *-a* option, otherwise Git will commit all the edits.
54 What if you've edited many files in many places? Reviewing each change one by
55 one becomes frustratingly mind-numbing. In this case, use *git add -i*, whose
56 interface is less straightforward, but more flexible. With a few keystrokes,
57 you can stage or unstage several files at a time, or review and select changes
58 in particular files only. Alternatively, run *git commit \--interactive* which
59 automatically commits after you're done.
61 === The Index: Git's Staging Area ===
63 So far we have avoided Git's famous 'index', but we must now confront it to
64 explain the above. The index is a temporary staging area. Git seldom shuttles
65 data directly between your project and its history. Rather, Git first writes
66 data to the index, and then copies the data in the index to its final
67 destination.
69 For example, *commit -a* is really a two-step process. The first step places a
70 snapshot of the current state of every tracked file into the index. The second
71 step permanently records the snapshot now in the index. Committing without the
72 *-a* option only performs the second step, and only makes sense after running
73 commands that somehow change the index, such as *git add*.
75 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 on what gets written to history, and are forced to 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.
77 === Don't Lose Your HEAD ===
79 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:
81  $ git reset HEAD~3
83 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.
85 But how can you go back to the future? The past commits know nothing of the future.
87 If you have the SHA1 of the original HEAD then:
89  $ git reset SHA1
91 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:
93  $ git reset ORIG_HEAD
95 === HEAD-hunting ===
97 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.
99 By default, Git keeps a commit for at least two weeks, even if you ordered
100 Git to destroy the branch containing it. The trouble is finding the appropriate
101 hash. You could look at all the hash values in `.git/objects` and use trial
102 and error to find the one you want. But there's a much easier way.
104 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.
106 The reflog command provides a friendly interface to these log files. Try
108   $ git reflog
110 Instead of cutting and pasting hashes from the reflog, try:
112  $ git checkout "@{10 minutes ago}"
114 Or checkout the 5th-last visited commit via:
116  $ git checkout "@{5}"
118 See the ``Specifying Revisions'' section of *git help rev-parse* for more.
120 You may wish to configure a longer grace period for doomed commits. For
121 example:
123   $ git config gc.pruneexpire "30 days"
125 means a deleted commit will only be permanently lost once 30 days have passed
126 and *git gc* is run.
128 You may also wish to disable automatic invocations of *git gc*:
130   $ git config gc.auto 0
132 in which case commits will only be deleted when you run *git gc* manually.
134 === Building On Git ===
136 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.
138 One easy trick is to use built-in Git aliases to shorten your most frequently
139 used commands:
141   $ git config --global alias.co checkout
142   $ git config --global --get-regexp alias  # display current aliases
143   alias.co checkout
144   $ git co foo                              # same as 'git checkout foo'
146 Another is to print the current branch in the prompt, or window title.
147 Invoking
149   $ git symbolic-ref HEAD
151 shows the current branch name. In practice, you most likely want to remove
152 the "refs/heads/" and ignore errors:
154   $ git symbolic-ref HEAD 2> /dev/null | cut -b 12-
156 The +contrib+ subdirectory is a treasure trove of tools built on Git.
157 In time, some of them may be promoted to official commands. On Debian and
158 Ubuntu, this directory lives at +/usr/share/doc/git-core/contrib+.
160 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:
162   $ git-new-workdir an/existing/repo new/directory
164 The new directory and 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.
166 === Daring Stunts ===
168 These days, Git makes it difficult for the user to accidentally destroy data.
169 But if you know what you are doing, you can override safeguards for common
170 commands.
172 *Checkout*: Uncommitted changes cause checkout to fail. To destroy your changes, and checkout a given commit anyway, use the force flag:
174   $ git checkout -f COMMIT
176 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.
178 *Reset*: Reset also fails in the presence of uncommitted changes. To force it through, run:
180   $ git reset --hard [COMMIT]
182 *Branch*: Deleting branches fails if this causes changes to be lost. To force a deletion, type:
184   $ git branch -D BRANCH  # instead of -d
186 Similarly, attempting to overwrite a branch via a move fails if data loss would ensue. To force a branch move, type:
188   $ git branch -M [SOURCE] TARGET  # instead of -m
190 Unlike checkout and reset, these two commands defer data destruction. The
191 changes are still stored in the .git subdirectory, and can be retrieved by
192 recovering the appropriate hash from `.git/logs` (see "HEAD-hunting" above).
193 By default, they will be kept for at least two weeks.
195 *Clean*: Some git commands refuse to proceed because they're worried about
196 clobbering untracked files. If you're certain that all untracked files and
197 directories are expendable, then delete them mercilessly with:
199   $ git clean -f -d
201 Next time, that pesky command will work!
203 === Improve Your Public Image ===
205 Stupid mistakes abound in the histories of many of my projects. The most
206 frightening are missing files due to forgetting to run *git add*. Luckily I
207 have yet to lose crucial data though accidental omission because I rarely
208 delete original working directories. I typically notice the error a few commits
209 later, so the only damage is a bit of missing history and a sheepish admission
210 of guilt.
212 I also regularly commit (literally and git-erally) the lesser transgression of
213 trailing whitespace. Though harmless, I wish these also never appeared on the
214 public record.
216 In addition, though unscathed so far, I worry about leaving merge conflicts
217 unresolved. Usually I catch them when I build a project, but there are some
218 cases this can overlook.
220 If only I had bought idiot insurance by using a _hook_ to alert me about these
221 problems:
223  $ cd .git/hooks
224  $ cp pre-commit.sample pre-commit  # Older Git versions: chmod +x pre-commit
226 Now Git aborts a commit if useless whitespace or unresolved merge conflicts are
227 detected.
229 For this guide, I eventually added the following to the beginning of the
230 *pre-commit* hook to guard against absent-mindedness:
232  if git ls-files -o | grep '\.txt$'; then
233    echo FAIL! Untracked .txt files.
234    exit 1
235  fi
237 Several git operations support hooks; see *git help hooks*. One can write hooks
238 to complain about spelling mistakes in commit messages, add new files, indent
239 paragraphs, append an entry to a webpage, play a sound, and so on.
241 We encountered the *post-update* hook earlier when discussing Git over
242 HTTP. This hook updates a few files Git needs for non-native communication.