Spun off some sections into a new chapter on history operations.
[gitmagic/gitmagic.git] / history.txt
blobdaeba0e4ffc7074c775ce485b8e5bb0147be1953
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:
5 only rewrite that part of history which you alone possess. Just as nations
6 forever argue on who committed what atrocity, if someone else has a clone whose
7 version of history differs to yours, you will have trouble reconciling when
8 your trees interact.
10 Of course, if you control all the other trees too, then there is no problem
11 since you can overwrite them.
13 Some developers strongly feel history should be immutable, warts and all.
14 Others feel trees should be made presentable before they are unleashed in
15 public. Git accommodates both viewpoints. Like cloning, branching and merging,
16 rewriting history is simply another power Git gives you, and it is up to you
17 to decide how to use it.
19 === I Stand Corrected ===
21 Did you just commit, but wish you had typed a different message? Then run:
23  $ git commit --amend
25 to change the last message. Realized you forgot to add a file? Run *git add* to
26 add it, and then run the above command.
28 Want to include a few more edits in that last commit? Then make those edits and run:
30  $ git commit --amend -a
32 === ... And Then Some ===
34 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. This is quite likely if you've been saving early and saving often. Then type
36  $ git rebase -i HEAD~10
38 and the last 10 commits will appear in your favourite $EDITOR. A sample excerpt:
40     pick 5c6eb73 Added repo.or.cz link
41     pick a311a64 Reordered analogies in "Work How You Want"
42     pick 100834f Added push target to Makefile
44 Then:
46 - Remove commits by deleting lines.
47 - Reorder commits by reordering lines.
48 - Replace "pick" with "edit" to mark a commit for amending.
49 - Replace "pick" with "squash" to merge a commit with the previous one.
51 Next run *git commit \--amend* if you marked a commit for editing. Otherwise, run:
53  $ git rebase --continue
55 === Local Changes Last ===
57 You're working on an active project. You make some local commits over time, and
58 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.
60 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.
62 This is a job for *git rebase* as described above. In many cases you can use
63 the *\--onto* flag and avoid interaction.
65 Also see *git help rebase* for detailed examples of this amazing command. You can split commits. You can even rearrange branches of a tree.
67 === Rewriting History ===
69 Occasionally, there are situations that call for the equivalent of the
70 Stalinesque practice of airbrushing people out of official photos, erasing them
71 from history. For example, suppose we intend to release a project, but it
72 involves a file that should be kept private for some reason. Perhaps I left my
73 credit card number in a text file and accidentally added it to the project.
74 Deleting the file is insufficient, for the file can be accessed from older
75 commits. We must remove the file from all commits:
77  $ git filter-branch --tree-filter 'rm top/secret/file' HEAD
79 See *git help filter-branch*, which discusses this example and gives a faster
80 method. In general, *filter-branch* lets you alter large sections of history with a single command.
82 Afterwards, you must replace all clones of your project with your revised version if you wish to interact with them later.
84 === Making History ===
86 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.
88 Otherwise, take a look at *git fast-import*. This command takes text input in a specific format and creates Git history from scratch. Typically a script is cobbled together and run once to feed this command, migrating the project in a single shot.
90 As an example, paste the following listing into temporary file, such as `/tmp/history`:
91 ----------------------------------
92 commit refs/heads/master
93 committer Alice <alice@example.com> Thu, 01 Jan 1970 00:00:00 +0000
94 data <<EOT
95 Initial commit.
96 EOT
98 M 100644 inline hello.c
99 data <<EOT
100 #include <stdio.h>
102 int main() {
103   printf("Hello, world!\n");
104   return 0;
109 commit refs/heads/master
110 committer Bob <bob@example.com> Tue, 14 Mar 2000 01:59:26 -0800
111 data <<EOT
112 Replace printf() with write().
115 M 100644 inline hello.c
116 data <<EOT
117 #include <unistd.h>
119 int main() {
120   write(1, "Hello, world!\n", 14);
121   return 0;
125 ----------------------------------
127 Then create a Git repository from this temporary file by typing:
129  $ mkdir project; cd project; git init
130  $ git fast-import < /tmp/history
132 You can checkout the latest version of the project with:
134  $ git checkout master .