summaryrefslogtreecommitdiff
path: root/docs/git/survival.md
blob: 60d1b620c7002b509e9fa691000f5046e906a778 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# Git Survival Guide

I think the `git` UI is pretty awful, and encourages using Git in ways that
will screw you. Here are a few things I've picked up that have saved my bacon.

* You will inevitably need to understand Git's “internals” to make use of it
  as an SCM tool. Accept this early. If you think your SCM tool should not
  expose you to so much plumbing, [don't](http://mercurial.selenic.com)
  [use](http://bazaar.canonical.com) [Git](http://subversion.apache.org).
    * Git weenies will claim that this plumbing is what gives Git all of its
      extra power. This is true; it gives Git the power to get you out of
      situations you wouldn't be in without Git.
* `git log --graph --decorate --oneline --color --all`
* Run `git fetch` habitually. Stale remote-tracking branches lead to sadness.
* `git push` and `git pull` are **not symmetric**. `git push`'s
  opposite operation is `git fetch`. (`git pull` is equivalent to `git fetch`
  followed by `git merge`, more or less).
* [Git configuration values don't always have the best defaults](config).
* The upstream branch of `foo` is `foo@{u}`. The upstream branch of your
  checked-out branch is `HEAD@{u}` or `@{u}`. This is documented in `git help
  revisions`.
* You probably don't want to use a merge operation (such as `git pull`) to
  integrate upstream changes into topic branches. The resulting history can be
  very confusing to follow, especially if you integrate upstream changes
  frequently.
    * You can leave topic branches “real” relatively safely. You can do
      a test merge to see if they still work cleanly post-integration without
      actually integrating upstream into the branch permanently.
    * You can use `git rebase` or `git pull --rebase` to transplant your
      branch to a new, more recent starting point that includes the changes
      you want to integrate. This makes the upstream changes a permanent part
      of your branch, just like `git merge` or `git pull` would, but generates
      an easier-to-follow history. Conflict resolution will happen as normal.
* Example test merge, using `origin/master` as the upstream branch and `foo`
  as the candidate for integration:

        git fetch origin
        git checkout origin/master -b test-merge-foo
        git merge foo
        # run tests, examine files
        git diff origin/master..HEAD

    To discard the test merge, delete the branch after checking out some other
    branch:

        git checkout foo
        git branch -D test-merge-foo

    You can combine this with `git rerere` to save time resolving conflicts in
    a later “real,” permanent merge.

* You can use `git checkout -p` to build new, tidy commits out of a branch
  laden with “wip” commits:

        git fetch
        git checkout $(git merge-base origin/master foo) -b foo-cleaner-history
        git checkout -p foo -- paths/to/files
        # pick out changes from the presented patch that form a coherent commit
        # repeat 'git checkout -p foo --' steps for related files to build up
        # the new commit
        git commit
        # repeat 'git checkout -p foo --' and 'git commit' steps until no diffs remain

    * Gotcha: `git checkout -p` will do nothing for files that are being
      created. Use `git checkout`, instead, and edit the file if necessary.
      Thanks, Git.
    * Gotcha: The new, clean branch must diverge from its upstream branch
      (`origin/master`, in the example above) at exactly the same point, or
      the diffs presented by `git checkout -p foo` will include chunks that
      revert changes on the upstream branch since the “dirty” branch was
      created. The easiest way to find this point is with `git merge-base`.

## Useful Resources

That is, resoures that can help you solve problems or understand things, not
resources that reiterate the man pages for you.

* Sitaram Chamarty's [git concepts
  simplified](http://sitaramc.github.com/gcs/)
* Tv's [Git for Computer
  Scientists](http://eagain.net/articles/git-for-computer-scientists)