Moved Personal Experience section to chapter on history.
[gitmagic/gitmagic.git] / history.txt
blob11764f84328ecc3dabceb89e7c1c5425f791f04d
1 == Lessons of History ==
3 A consequence of the distributed nature of Git is that history can be edited
4 easily. But if you tamper with the past, take care: only rewrite that part of
5 history which you alone possess. Just as nations forever argue over who
6 committed what atrocity, if someone else has a clone whose version of history
7 differs to yours, you will have trouble reconciling when your trees interact.
9 Of course, if you control all the other trees too, then there is no problem
10 since you can overwrite them.
12 Some developers strongly feel history should be immutable, warts and all.
13 Others feel trees should be made presentable before they are unleashed in
14 public. Git accommodates both viewpoints. Like cloning, branching and merging,
15 rewriting history is simply another power Git gives you, and it is up to you
16 to decide how to use it.
18 === I Stand Corrected ===
20 Did you just commit, but wish you had typed a different message? Then run:
22  $ git commit --amend
24 to change the last message. Realized you forgot to add a file? Run *git add* to
25 add it, and then run the above command.
27 Want to include a few more edits in that last commit? Then make those edits and run:
29  $ git commit --amend -a
31 === ... And Then Some ===
33 Let's suppose the previous problem is ten times worse. After a lengthy session you've made a bunch of commits. But you're not quite happy with the way they're organized, and some of those commit messages could use rewording. Then type:
35  $ git rebase -i HEAD~10
37 and the last 10 commits will appear in your favourite $EDITOR. A sample excerpt:
39     pick 5c6eb73 Added repo.or.cz link
40     pick a311a64 Reordered analogies in "Work How You Want"
41     pick 100834f Added push target to Makefile
43 Then:
45 - Remove commits by deleting lines.
46 - Reorder commits by reordering lines.
47 - Replace "pick" with "edit" to mark a commit for amending.
48 - Replace "pick" with "squash" to merge a commit with the previous one.
50 If you marked a commit for editing, then run:
52  $ git commit --amend
54 Otherwise, run:
56  $ git rebase --continue
58 So commit early and commit often: you can easily tidy up later with rebase.
60 === Local Changes Last ===
62 You're working on an active project. You make some local commits over time, and
63 then you sync with the official tree with a merge. This cycle repeats itself a few times before you're ready to push to the central tree.
65 But now the history in your local Git clone is a messy jumble of your changes and the official changes. You'd prefer to see all your changes in one contiguous section, and after all the official changes.
67 This is a job for *git rebase* as described above. In many cases you can use
68 the *\--onto* flag and avoid interaction.
70 Also see *git help rebase* for detailed examples of this amazing command. You can split commits. You can even rearrange branches of a tree.
72 === Rewriting History ===
74 Occasionally, you need the source control equivalent of airbrushing people out
75 of official photos, erasing them from history in a Stalinesque fashion. For
76 example, suppose we intend to release a project, but it involves a file that
77 should be kept private for some reason. Perhaps I left my credit card number in
78 a text file and accidentally added it to the project. Deleting the file is
79 insufficient, for the file can be accessed from older commits. We must remove
80 the file from all commits:
82  $ git filter-branch --tree-filter 'rm top/secret/file' HEAD
84 See *git help filter-branch*, which discusses this example and gives a faster
85 method. In general, *filter-branch* lets you alter large sections of history
86 with a single command.
88 Afterwards, you must replace clones of your project with your revised version if you wish to interact with them later.
90 === Making History ===
92 Want to migrate a project to Git? If it's managed with one of the more well-known systems, then chances are someone has already written a script to export the whole history to Git.
94 Otherwise, look up *git fast-import*, which reads text input in a specific
95 format to create Git history from scratch. Typically a script using this
96 command is hastily cobbled together and run once, migrating the project in a
97 single shot.
99 As an example, paste the following listing into temporary file, such as `/tmp/history`:
100 ----------------------------------
101 commit refs/heads/master
102 committer Alice <alice@example.com> Thu, 01 Jan 1970 00:00:00 +0000
103 data <<EOT
104 Initial commit.
107 M 100644 inline hello.c
108 data <<EOT
109 #include <stdio.h>
111 int main() {
112   printf("Hello, world!\n");
113   return 0;
118 commit refs/heads/master
119 committer Bob <bob@example.com> Tue, 14 Mar 2000 01:59:26 -0800
120 data <<EOT
121 Replace printf() with write().
124 M 100644 inline hello.c
125 data <<EOT
126 #include <unistd.h>
128 int main() {
129   write(1, "Hello, world!\n", 14);
130   return 0;
134 ----------------------------------
136 Then create a Git repository from this temporary file by typing:
138  $ mkdir project; cd project; git init
139  $ git fast-import < /tmp/history
141 You can checkout the latest version of the project with:
143  $ git checkout master .
145 === Personal Experience ===
147 In a centralized version control system, history modification is a difficult
148 operation, and only available to administrators. Cloning, branching, and
149 merging are impossible without network communication. So are basic operations
150 such as browsing history, or committing a change. In some systems, users
151 require network connectivity just to view their own changes or open a file for
152 editing.
154 Centralized systems preclude working offline, and need more expensive network
155 infrastructure, especially as the number of developers grows. Most
156 importantly, all operations are slower to some degree, usually to the point
157 where users shun advanced commands unless absolutely necessary. In extreme
158 cases this is true of even the most basic commands. When users must run slow
159 commands, productivity suffers because of an interrupted work flow.
161 I experienced these phenomena first-hand. Git was the first version control
162 system I used. I quickly grew accustomed to it, taking many features for
163 granted. I simply assumed other systems were similar: choosing a version
164 control system ought to be no different from choosing a text editor or web
165 browser.
167 I was shocked when later forced to use a centralized system. My often flaky
168 internet connection matters little with Git, but makes development unbearable
169 when it needs to be as reliable as local disk. Additionally, I found myself
170 conditioned to avoid certain commands because of the latencies involved, which
171 ultimately prevented me from following my desired work flow.
173 When I had to run a slow command, the interruption to my train of thought
174 dealt a disproportionate amount of damage. While waiting for server
175 communcation to complete, I'd do something else to pass the time, such as
176 check email or write documentation. By the time I returned to the original
177 task, the command had finished long ago, and I would waste more time trying to
178 remember what I was doing. Humans are bad at context switching.
180 There was also an interesting tragedy-of-the-commmons effect: anticipating
181 network congestion, individuals would consume more bandwidth than necessary on
182 various operations in an attempt to reduce future delays. The combined efforts
183 intensified congestion, encouraging individuals to consume even more bandwidth
184 next time to avoid even longer delays.