Many minor edits
[gitmagic.git] / secrets.txt
bloba595742b0198e39da6766d33f44103047c3e1285
1 = Git's Secrets Revealed =
3 We take a peek under the hood and explain how Git performs its miracles. I will skimp over details. For in-depth descriptions refer to one of the [[.][references]].
5 == Invisibility ==
7 How can Git be so unobtrusive? Aside from occasional commits and merges, you can work as if you weren't aware that version control exists. That is, until you need it, and that's when you're glad Git was watching over you the whole time.
9 Other version control systems don't let you forget about them. Permissions of files may be read-only unless you explicity tell the server which files you intend to edit. The central server might be keeping track of who's checked out which code, and when. When the network goes down, you'll soon suffer. Developers constantly struggle with virtual red tape and bureaucracy.
11 The secret is the ".git" directory in your working directory. Git keeps the history of your project here. The initial "." stops it showing up in <tt>ls</tt> listings. Except when you're pushing and pulling changes, all version control operations operate within this directory.
13 You have total control over the fate of your files because Git doesn't care what you do to them. Git can easily recreate a saved state from ".git" at any time.
15 == Bare Repositories ==
17 You may have been wondering what format those online Git repositories use.
18 They're plain Git repositories, just like your ".git" directory except they've got names like "proj.git", and they have no working directory associated with them.
20 == Integrity ==
22 Most people associate cryptography with keeping things secret, but another equally important goal is ensuring integrity. Proper use of cryptographic hash functions can prevent accidental or malicious data corruption.
24 A SHA1 hash can be thought of as a unique 160-bit ID number for every string of bytes you'll encounter in your life. Actually more than that: every string of bytes that any human will ever use over many lifetimes. The hash of the whole contents of a file can be viewed as a unique ID number for that file.
26 An important observation is that a SHA1 hash is itself a string of bytes, so we can hash strings of bytes containing other hashes.
28 Roughly speaking, all files handled by Git are referred to by their unique ID, not by their filename. You can see for yourself: all data resides in files in the ".git/objects" subdirectory, where you won't find any normal filenames.
30 The filenames are actually recorded in ''tree'' objects, which are lists of filenames along with the IDs of their contents. Since the tree itself is a string of bytes, it too has a unique ID, which is how it is stored in the ".git/objects" subdirectory. Trees can appear on the lists of other trees, hence a directory tree and all the files within may be represented by trees and blobs.
32 Lastly, a ''commit'' contains a message, a few tree IDs and information on how they are related to each other. A commit is also a string of bytes, hence it too has a unique ID.
34 Now suppose somebody tries to rewrite history and attempts to change the contents of a file in an ancient version. Then the ID of the file will change since it's now a different string of bytes. This changes the ID of any tree object referencing this file, which in turn changes the ID of all commit objects involving this tree. The corruption in the bad respository is exposed when everyone realizes all the commits since the mutilated file have the wrong IDs.
36 I've ignored details such as file permissions and signatures. See the
37 [[.][references]] for the full story. But in short, so long as the 20 bytes representing the last commit are safe, it's impossible to tamper with a Git repository.
39 == Git Shortcomings ==
41 There are some Git issues I've swept under the carpet until now. Some can be handled easily with scripts, others require reorganizing or redefining the project, and as for Windows annoyances, one will just have to wait. Or better yet, pitch in and help!
43 === Windows Git ===
45 Git on Window can be cumbersome. It works with Cygwin installed, though is slower. There is also a [[http://repo.or.cz/w/git/mingw.git][mingw port]] whose setup is less invasive as it can be run from the Windows command-line.
47 === Unrelated Files ===
49 If your project is very large and contains many unrelated files that are constantly being changed, Git may be disadvantaged more than other systems because single files are not tracked. Git tracks changes to the whole project, which is usually beneficial.
51 A solution is to break up your project into pieces, each consisting of files that are related.
53 === Volatile Projects ===
55 Git was written to be fast with respect to the size of the changes. Humans make small edits from version to version. A one-liner bugfix here, a new feature there, ammended comments, that sort of thing. But if you're mostly keeping files that are radically different in successive revisions, on each commit, your history necessarily grows by the size of your whole project.
57 There is nothing any version control system can do about this, but standard Git users will suffer more since normally histories are cloned.
59 The reasons why the changes are so great should be examined. Perhaps file formats should be changed. Recording minor edits should not require drastic changes to every file.
61 Or perhaps a database or backup/archival solution is what is actually being sought, not a version control system. For example, version control may not be suitable for managing photos periodically taken from a webcam. Again, version control is meant for keeping track of alterations made by humans.
63 If the files really must be constantly morphing and a version control really must be used, a possibility is to use Git in a centralized fashion. With some simple scripting, one can checkout files without their histories. Of course, most Git tools will be unavailable. This is probably fine as it's unclear how the history of wildly unstable files can help anyone.
65 === Global Counter ===
67 Some centralized version control systems maintain a positive integer that increases when a new commit is accepted. Git refers to changes by their hash, which is better in many circumstances.
69 But some people like having this integer around. Luckily, it's easy to write scripts so that with every update, the central Git repository increments an integer, perhaps in a tag, and associates it with the hash of the latest commit.
71 Actually, every clone could maintain such a counter, but this would probably not be useful, since everyone only really cares about the central repository and its counter.
73 === Automatic Compression ===
75 To save space, <tt>git-gc</tt> should be run once in a while. Some complain because this must be done manually.
77 If this is a major concern, scripts should be written to run this program automatically. Ideally it should occur when during periods of little activity.