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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
* How dCVS is different
** Everything is implicitly a branch
The only ``central'' repository is the one you're in. Distribution of
changes is a separate command. This means every repository is an
inevitable branch of the first commit.
** Merge becomes a required operation
Since everything is a branch, a history merge is required in order to
share changes up-or-downstream.
** History is non-linear
No more monotonically increasing version numbers. Instead version
numbers must be crafted to at least identify the data of the commit
itself so they can be universally addressable.
* Create a demo repo
** create
~% mkdir sifl
~% cd sifl
~/sifl% git init
Initialized empty Git repository in /Users/bjc/Documents/git/sifl/.git/
** clone
~/sifl% cd ..
~% git clone sifl olly
Initialized empty Git repository in /Users/bjc/Documents/git/olly/.git/
~% cd olly
~/olly% git remote show origin # Automatically set up and pointing to
# ../sifl
* remote origin
URL: ../sifl
* Add some data
** sifl commands
~% cd sifl
~/sifl% echo sifl > whoami
~/sifl% git add whoami; git commit -m "Set whoami to sifl."
[master (root-commit) b211a60] Set whoami to sifl.
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 whoami
** A moment on git refs
*** commit id
A git commit id includes a hash of the commit blob as well as a
reference to the commit's parent. In this way a given commit and its
history can be compared simply by checking the id. All other refs
inevitably point to a commit id as the fundamental unit.
*** HEAD
This is the commit the working copy is based off of. Upon commit this
will be used as the parent commit.
*** branch
A branch is a moving HEAD pointer. All working directories are
implicitly branches, although it's easier to use a named one.
*** tag
A tag is a commit id with an optional message and signature.
** sifl commit history graph
(b211a60)
O
** olly commands
~/sifl% cd ../olly
~/olly% echo olly > whoami
~/sifl% git add whoami; git commit -m "Set whoami to olly."
[master (root-commit) 536a095] Set whoami to olly.
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 whoami
** olly commit history graph
(536a095)
O
* Sharing changes
** sifl commands
~% cd sifl
~/sifl% git pull ../olly
warning: no common commits
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From ../olly
* branch HEAD -> FETCH_HEAD
Auto-merging whoami
CONFLICT (add/add): Merge conflict in whoami
Automatic merge failed; fix conflicts and then commit the result.
[1] 16566 exit 1 git pull ../olly
~/sifl% cat whoami
<<<<<<< HEAD:whoami
sifl
=======
olly
>>>>>>> 536a095305749bacf3357e37eeb13676e8f9c4d0:whoami
~/sifl% echo sifl > whoami; echo olly >> whoami
~/sifl% git add whoami; git commit -m "Fix conflicts."
[master eb69ba9] Fix conflicts.
** sifl commit history graph
(b211a60)
O ------- O (eb69ba9)
/
O -----/
(536a095)
** merge commits
* No semantic difference between branches and repositories
** repositories are just part of the ref
Repositories are implicitly branches, therefor, you can push and pull
to branches in local repositories, although it is a little silly.
* Rewriting (some) history
** Rewrite as much as you want, but be careful
You can make your local history look however you want, but since git
commit ids include parent references as well as the commit itself, you
can make your repository look totally different from everyone else's,
making sharing changes difficult.
** git complains under some circumstances for push and pull - elaborate
** Reordering and merging patches
*** Why would you do this?
1. Need to get a feature out, but mixed in unwanted code.
2. Presenting a logical history
3. Segregating features for independant testing and acceptance.
** Splitting patches w/ git-add --patch
** git rebase -i
** Using rebase with git-add --patch/git-reset to split changes
* Screwing up your repo and fixing your changes
** git reflog
** git reset
* Merge strategies
** fast-forward
** recursive
** octopus
** any more?
* Brief `git svn' overview
** Importing linear branches is straight-forward.
** Use `rebase' if you intend to use `dcommit.'
** SVN branches auto-tracked, just like master.
|