This repository has been archived by the owner on Mar 14, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 77
/
branching.html
221 lines (158 loc) · 12.7 KB
/
branching.html
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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Learn.GitHub - Branching and Merging</title>
<script type="text/javascript" src="../js/jquery-1.2.6.pack.js"></script>
<script type="text/javascript" src="../js/thickbox-compressed.js"></script>
<script type="text/javascript" src="../js/jquery.corner.js"></script>
<link rel="stylesheet" href="../css/screen.css" type="text/css" media="screen, projection">
<link rel="stylesheet" href="../css/print.css" type="text/css" media="print">
<!--[if IE]>
<link rel="stylesheet" href="../css/ie.css" type="text/css" media="screen, projection">
<![endif]-->
<link rel="stylesheet" href="../css/style.css" type="text/css" media="screen" charset="utf-8"/>
<link rel="stylesheet" href="../css/thickbox.css" type="text/css" media="screen"/>
</head>
<body>
<div class="container">
<div class="span-21" id="header">
<div class="span-10">
<a href="/"><img src="../images/learn.github.png" alt="github learn logo" /></a>
</div>
<div class="span-11 last">
<div id="links">
<a href="http://github.com">home</a>
<a href="http://github.com/login">login</a>
<a href="http://github.com/signup">signup!</a>
</div>
</div>
</div>
<div class="span-21" id="welcome">
<h1>Branching and Merging</h1>
<p>Create and work on topic and long running branches, merge between them and delete them.</p>
</div>
<div class="content">
<div class="span-21"><hr/><p>As we touched on in the first lesson, the way that Git handles branching and merging is pretty unique. First of all, it’s incredibly fast, both to create new branches and to switch between them. Git has a single working directory that it replaces with the contents of the branch you’re working on, so you don’t have to have separate directories for each branch.</p>
<p>In this lesson, we’ll create a new branch, do a bit of work, switch back to our stable branch (generally called ‘master’ in Git by default), do some work there, switch back to our temporary branch to complete our work, and then merge it into our stable branch.</p>
<p>To view our available branches, we run the ‘git branch’ command with no arguments.</p>
<pre><code>$ git branch
* master</code></pre>
<p>We can see that we only have one branch ‘master’ and the ’*’ indicates that we are currently on it. For the purposes of illustrating this, I will show the commit history model. Here, the green boxes are each commit and the arrows are where each commit points to for its parent or parents. This is basically how Git actually stores its commit data.</p>
<p><img alt='Branch Step 1' src='../images/branch/step1.png' /></p>
<p>You can see, in Git, branches are simply lightweight pointers to a particular commit. The history is simply figured out by traversing the parents, one commit at a time.</p>
<h3 id='creating_new_branches'>creating new branches</h3>
<p>To create a new branch, we can use ‘git branch (branchname)’ which will create a branch at the point we’re currently at.</p>
<pre><code>$ git branch experiment</code></pre>
<p><img alt='Branch Step 2' src='../images/branch/step2.png' /></p>
<p>To switch to that branch so that the work we do is saved to it instead of the ‘master’ branch, we run the ‘git checkout’ command’</p>
<pre><code>$ git checkout experiment
Switched to branch "experiment"
$ git branch
* experiment
master</code></pre>
<p>Now we can see that we have a new branch and that we’re on it. Now we can edit files and commit without worrying about messing up our pristine ‘master’ branch that we know works perfectly. We don’t have to share the changes we make in our ‘experiment’ branch until we are certain they are ready.</p>
<h3 id='working_in_multiple_branches'>working in multiple branches</h3>
<p>So, let’s add a TODO file, make a change to the ‘simplegit.rb’ file, and then make a commit with both changes in it.</p>
<pre><code>$ vim lib/simplegit.rb
$ vim TODO
$ git add TODO
$ git commit -am 'added a todo and added simplegit functions'
[experiment]: created 4682c32: "added a todo and added simplegit functions"
2 files changed, 10 insertions(+), 0 deletions(-)
create mode 100644 TODO</code></pre>
<p><img alt='Branch Step 3' src='../images/branch/step3.png' /></p>
<p>Now if we take a look, we can see that we have 3 files and one subdirectory.</p>
<pre><code>$ ls
README Rakefile TODO lib</code></pre>
<p>So, let’s now suppose that we need to go back and make a bugfix on our original verison of the simplegit.rb file. We can revert back to where our project was before we branched with the ‘checkout command.</p>
<pre><code>$ git checkout master
Switched to branch "master"
$ ls
README Rakefile lib</code></pre>
<p>Now we can see that our working directory no longer has the TODO file it in - that’s because the master branch didn’t have that file. If we do a commit here and then switch back, we’ll see the TODO file there again, and the simplegit.rb file reverted back to where we left it in the experiment branch.</p>
<pre><code>$ vim lib/simplegit.rb
$ git commit -am 'added a commit function'
[master]: created 0b7434d: "added a commit function"
1 files changed, 4 insertions(+), 0 deletions(-)
$ git checkout experiment
Switched to branch "experiment"
$ ls
README Rakefile TODO lib</code></pre>
<p><img alt='Branch Step 4' src='../images/branch/step4.png' /></p>
<p>We could even go back to the master branch and create a new branch and start committing there. Most Git developers will have several branches running at the same time, each with a specific theme or focus - a new feature or bug fix that lasts hours or even minutes, or longer running branches for large scale refactorings that periodically merge in changes from mainline branches.</p>
<p>This practice of cooking your features and changes in branch silos makes it easy and cheap to context switch rapidly and without complications. If you want to work on a longer running branch with another developer, you can push branches up to a shared server. For example, if you wanted to work on the experiment branch with someone else, you can push it to your server like so:</p>
<pre><code>$ git push origin experiment</code></pre>
<p>The next pull your collaborator does will pull that work down and let them work on it with you. However, Git also importantly lets you keep these branches private if you want - simply don’t push them.</p>
<h3 id='merging_and_removing_finished_branches'>merging and removing finished branches</h3>
<p>When you are done with work on a branch, you can either remove it and ignore the changes made on it if the work is not acceptable, or you can merge it into one of your long running branches (some developers will have ‘master’ only contain stable code, a parallel ‘develop’ branch that you use to integrate and test changes, and shorter lived topic branches for day to day work).</p>
<p>To merge a branch in, switch to the branch you want to merge into and run the ‘git merge’ command. If it can merge cleanly, you’ll simply see something like this:</p>
<pre><code>$ git merge experiment
Auto-merging lib/simplegit.rb
Merge made by recursive.
lib/simplegit.rb | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)</code></pre>
<p>Easy peasy - you’re merged.</p>
<p><img alt='Branch Step 5' src='../images/branch/step5.png' /></p>
<h3 id='merge_conflict_resolution'>merge conflict resolution</h3>
<p>However, sometimes things don’t go so smoothly If you get a merge conflict, you’ll see something like this instead.</p>
<pre><code>$ git merge experiment
Auto-merging lib/simplegit.rb
CONFLICT (content): Merge conflict in lib/simplegit.rb
Automatic merge failed; fix conflicts and then commit the result.</code></pre>
<p>In this case it will tell you the files that did not merge cleanly, and you can simply resolve the conflicts manually. If I open up the file it says failed, I’ll see normal merge conflict markers in it.</p>
<pre><code><<<<<<< HEAD:lib/simplegit.rb
def commit(message)
command("git commit -m '#{message}'")
=======
def add(path)
command("git add #{path}")
>>>>>>> experiment:lib/simplegit.rb
end</code></pre>
<p>When you’re done fixing it, all you have to do is run ‘git add’ on the file to re-stage it, which marks it as resolved. Then commit the merge.</p>
<pre><code>$ git add lib/simplegit.rb
$ git commit
[master]: created 6d52a27: "Merge branch 'experiment'"</code></pre>
<h3 id='merging_multiple_times'>merging multiple times</h3>
<p>I point this out because it’s something that is generally difficult to do in some other VCSs, but is very easy in Git. That is, merging from a branch, then continuing to do work in it and merging again. This is often the case if you have a ‘development’ branch that you do integration testing and merge experimental changes into and then periodically merge it into your stable ‘master’ branch.</p>
<p>For example, let’s say we switched back to the ‘experiment’ branch, made a few changes, then at some point merged it back into ‘master’ again, making our history look something like this.</p>
<p><img alt='Branch Step 6' src='../images/branch/step6.png' /></p>
<p>Since Git does its merges as a simple 3 way merge based on the commit history snapshots, doing multiple merges is often very easy. It will only have to merge in changes introduced on both branches since the last merge - it will not have to re-merge anything.</p>
<p>When you are done with a branch, say in this case the ‘experiment’ branch, we can simply delete it with ‘git branch -d’</p>
<pre><code>$ git branch -d experiment</code></pre>
<p>If the branch has not been merged in at some point, in which case deleting the branch would lose changes, Git will not allow you to do it. If you <em>want</em> to lose the changes, simply use the ‘-D’ flag instead - that will force the deletion.</p>
<p>So, that is basic branching and merging in Git and should give you a good baseline for being able to effectively use this powerful and ultimately pretty simple tool.</p>
<p>For more information on branching and merging in Git, you can read <a href='http://progit.org/book/ch3-0.html'>Chapter 3</a> of the Pro Git book.</p><br/><br/><hr/></div><div class="span-10"><a href="normal.html">« Normal Workflow</a></div><div style="text-align:right" class="span-11 last"><a href="remotes.html">Distributed Git »</a></div><div class="span-24 last"> </div><hr/>
</div>
<div id="footer" class="span-21">
<div class="info span-12">
<div class="links">
<a href="https://github.com/blog/148-github-shirts-now-available">T-Shirts</a> |
<a href="https://github.com/blog">Blog</a> |
<a href="https://github.com/contact">Contact & Support </a> |
<a href="http://training.github.com/">Git Training</a> |
<a href="http://groups.google.com/group/github/">Google Groups</a> |
<a href="https://status.github.com">Status</a>
</div>
<div class="company">
© 2012 GitHub Inc. All rights reserved. | <a href="https://help.github.com/articles/github-terms-of-service">Terms of Service</a> | <a href="https://help.github.com/articles/github-privacy-policy">Privacy Policy</a>
</div>
</div>
<div class="fork span-7">
This website is <a href="http://github.com/github/learn.github.com">open source</a>.
Please help us by forking the project and adding to it.
</div>
</div>
</div>
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
var pageTracker = _gat._getTracker("UA-3769691-2");
pageTracker._initData();
pageTracker._trackPageview();
</script>
</body>
</html>