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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
|
Tag
git tag -a x.y.z -m "Tag version x.y.z"
Squash multiple commits into one
git rebase -i HEAD~<N>
http://www.gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html
Change commit message
git commit --amend
Revert uncommited changes
git reset --hard HEAD
Copy commit from one branch to the other
# On the source branch
git log -1
git cout <target-branch>
git cherry-pick <commit-id>
Setup remote repository
On remote:
1. Use the server/mkrepo.sh script:
mkdrepo.sh <name>
mkdrepo.sh --private <name>
<name> is without the .git suffix.
On local:
1. git remote add origin scm.codesynthesis.com:/var/scm/proj/proj.git
2. git push --tags origin master
3. # blow the local project and do clone
git clone scm.codesynthesis.com:/var/scm/proj/proj.git [name]
Delete a branch from a remote repository
git push origin :experimental
Find a ref that matches experimental in the origin repository (e.g.
refs/heads/experimental), and delete it.
Using the push.sh script:
./push.sh :<name>
Rebasing
Local (e.g., from a feature branch to master):
git rebase <src> [<dst>]
If <dst> is not specified, current branch is used. If <dst> is
specified, it is checked out.
Remote (e.g., merge someone else's changes):
git fetch
git rebase origin[/master]
git push --tags origin
History Cleanup
This is the overall process for cleaning up the history in a feature
branch before merging it into master. The goal is to end up with a
nice and clean history in master, without any divergences and merges
that usually the result of the git merge command.
Note: make sure you have rerere enabled for this process to work
smoothly (~/.gitconfig).
Note: if you are just learning this procedure, make a local backup
copy of your repository in case things go badly and you need to
start from scratch.
To achieve this we first merge any unmerged changes that may be on
master and then rebase the whole thing on master. The end result of
this step is a history that first has all the commits that are from
master followed by all the commit from the feature branch (in other
words, master is now a prefix of our history which means we can
fastforward-only (--ff-only) merge this history into it):
git cout feature
git merge master
git rebase master
At this stage, run gitk and verify that you now have a linear history
that starts with master.
The second step is to clean up the commit history of our feature
branch since it may have "dirty", work-in-progress commits. This may
involve squashing several commits into one, rewording commit messages,
and possibly reordering the commits. The swiss army knife for this
is the interactive git rebase:
git rebase -i HEAD~<N>
Where <N> is the number of commits you would like to cleanup. Generally,
if you want to work on all the commits on this feature branch run gitk
and count the number of commits from the top to the first commit that
is on master (and if you know a better way to achieve the same result,
let me know). That is your <N>.
Note also that the order of commits in the resulting edit file will
be the reverse of what you see in gitk.
Once in the edit file, use commands to squash, reword, or reorder
the history (note that squashing several commits automatically
means rewording the commit message). Note also that you can re-run
this command multiple times. For example, you can squash some
commits, then examine the history (with gitk), then squash some
more, etc.
Finally, once the history is cleaned up, we can merge it into
master:
git cout master
git merge --ff-only feature
Verify with gitk everything looks good on master and push:
git push
It is also a good idea to delete the feature branch, both locally
and on the origin:
git br -d feature
git push origin :feature
Submodules
git config --global status.submoduleSummary true
git config --global diff.submodule log
git submodule update --init # init and update
git clone --recursive # same as doing above manually
git submodule update --remote [sub] # update submodule(s) (to remote master)
# --rebase
git fetch
git checkout <commit-sha1> # As above but to specific commit.
git pull # fetches submodules, but does not update
git submodule update # must be done explicitly (--init --recursive)!
# Making changes, first make sure up-to-date with remote
#
git cout master # in submodule, to make changes, commit/push must be on both!
# If already made changes (in sub/):
git stash
git cout master
git stash pop
# Remove submodule.
#
git submodule deinit sub
git rm sub # then commit
|