3 =============== |
3 =============== |
4 |
4 |
5 Introduction |
5 Introduction |
6 ============ |
6 ============ |
7 |
7 |
8 The following statement from a blog[1](http://karlagius.com/2009/01/09/version-control-for-the-masses/") aptly points usefulness of version control systems: |
8 Version control is just a way to track your files over time and share them. |
9 |
9 This allows you to go back to older versions when something goes wrong, see |
10 "Version control is one of those weird, geeky things that never really gained much ground in non-geek fields, despite the fact that it’s blindingly useful. |
10 what changed when and why, collaborate on a single piece of work with a bunch |
11 |
11 of people. |
12 Version control (or source control) is nothing more complex than keeping copies of work as we make changes. On the surface, it’s all straight-forward; make a copy of every file before making any changes to it. That way, if something seriously messes up, one can always fall back to something that worked before, or at least compare the broken copy with one that used to work so one can figure out where it went wrong." |
12 |
13 |
13 Like this |
14 One probably cooks up their own version control system without realizing it had such a geeky name. For instances files with names oldxxxxxx.py and latestxxxxxx.py. Every time to make some change in a file, one save it with different name then the original one. Luckily there are like, loads of version control systems out there to do this heavy lifting. |
14 `blog <http://karlagius.com/2009/01/09/version-control-for-the-masses/>`_ |
|
15 aptly points out, "Version control is one of those weird, geeky things that |
|
16 never really gained much ground in non-geek fields, despite the fact that |
|
17 it’s blindingly useful." In this course, we are going to see a handful of |
|
18 such things, which are widely used in the programmer world, but not so much |
|
19 in the scientific computing world, even when if they would be very useful. |
|
20 |
|
21 Version control is just a way of backing up your files, before making changes |
|
22 to it. Most people would have cooked up their own version control system, |
|
23 without realizing, there are tools built by others, which make this task much |
|
24 more organized and systematic. You surely would've saved your files, some |
|
25 time or the other as ``oldproject.py``, ``latestproject.py`` and so on, or |
|
26 date-tagging them as ``project-21-01-10.py``, ``project-20-02-10.py`` and so |
|
27 on. |
15 |
28 |
16 Why Use Version Control |
29 Why Use Version Control |
17 ======================= |
30 ======================= |
18 |
31 |
19 One of idea behind Version Control Tools was to build onto very first step which can be creating a empty file, or writing a first buggy program for assignment, rather than simply loose it. So here are some more reasons why is automated version control needed: |
32 We have seen that one of the main motivation to use a version system control |
20 |
33 system is the ability to go back to a working version of the file, when |
21 - It will track the history and evolution of a project, so one don't have to do it manually. It allows to track what changes where made, when were they made, by whom and why. |
34 something stops working. Below are a few more advantages of using an |
22 - For a team of people working on same project, revision control software makes it easier to collaborate. For example, when people more or less simultaneously make potentially incompatible changes, the software will help them to identify and resolve those conflicts. |
35 automated version control system. |
23 - It can help to recover from mistakes. If a change made at some moment of time, turns out to be an error in future, one can revert to an earlier version of one or more files. In fact, a really good revision control tool will even help in efficiently figure out exactly when a problem was introduced. |
36 |
24 |
37 - It tracks the history and evolution of a project. It allows you to |
25 Most of these reasons are equally valid for the project having one man show, or hundred people. Besides projects, even it can be used to maintain assignments related to one particular subject/course, it will help manage things in way much better way. These tools can be used for better *resources management*. All codes, documents, presentation, assignments related to one course maintained in such a inventory can help avoiding accidental lose of data(deletion) and Internet hosting for version control will make the work immune to local hard-disk crash. |
38 track what changes were made at what point of time, when and by whom. |
|
39 |
|
40 - If you are collaborating, as a team on a project, a version control |
|
41 system will make it much easier for you to collaborate. It allows you |
|
42 to work simultaneously on the same file, without worrying about merging |
|
43 your changes. |
|
44 |
|
45 - A good version control system will help you efficiently track down bugs |
|
46 and pin-point the changes that introduced the bug, reducing your |
|
47 debugging time. |
|
48 |
|
49 Version control is as useful for a one man show, as it is for a big group of |
|
50 people working on a project. As a student, you can use it to maintain your |
|
51 course work, too. You could maintain a version controlled repository with all |
|
52 your code, assignments, and other documents. Keeping your stuff version |
|
53 controlled will help avoid accidental deletion of individual files etc. |
|
54 Hosting it on a remote server will protect you from a local hard disk crash. |
|
55 |
|
56 Mercurial |
|
57 ========= |
26 |
58 |
27 Some of Version Control Tools available and used widely are: |
59 Some of Version Control Tools available and used widely are: |
28 |
60 |
29 - cvs (Concurrent Version System) |
61 - ``cvs`` (Concurrent Versions System) |
30 - svn (Subversion) |
62 - ``svn`` (Subversion) |
31 - hg (Mercurial) |
63 - ``hg`` (Mercurial) |
32 - bzr (Bazaar) |
64 - ``git`` |
33 - git |
65 |
34 |
66 Each of these tools have some unique functionality and their own merits and |
35 Each of above mentioned tools have sets of feature which it offers in unique way. For this session we are going to concentrate on hg (mercurial). After covering the basics of hg, one can easily try other tools, and use what-ever he/she is most comfortable with. |
67 de-merits. In this course, we shall learn to use Mercurial or ``hg``. |
36 |
68 Once you know how to use ``hg``, you could easily try other tools and switch |
37 Learning the Lingo |
69 to one that you feel most comfortable with. |
38 ================== |
70 |
39 |
71 Why ``hg`` ? |
40 Here are some of terms which are going to used through out the rest of session: |
72 ------------ |
41 |
|
42 Basic Setup |
|
43 ----------- |
|
44 |
|
45 (should we include at all terms used by vcs's other than hg?) |
|
46 |
|
47 Repository(repo): |
|
48 The folder with all the files. |
|
49 Server: |
|
50 The system with the main(mother) repo. |
|
51 Trunk/Main: |
|
52 The “primary” location for code in the repo. Think of code as a family tree — the “trunk” is the main line. This is generally what is present on server. |
|
53 |
|
54 Basic Actions |
|
55 ------------- |
|
56 |
|
57 Add: |
|
58 Put a file into the repo for the first time, i.e. begin tracking it with Version Control. |
|
59 Head/Tip: |
|
60 The latest version of the repo(Die Hard 4.1) |
|
61 Revision: |
|
62 What version a file is on. |
|
63 Clone: |
|
64 Creating initial copy of the repo onto a local machine. |
|
65 Commit: |
|
66 Committing the changes done to the repo in terms of contents of the files or adding/removing of the files. |
|
67 Logs/History: |
|
68 Logs of all the past changes done to the repo. |
|
69 Update: |
|
70 Updating the local repo with the main one, includes both, adding changing done by us or importing changes done by others. |
|
71 Revert: |
|
72 Going back to previous committed state of file. |
|
73 |
|
74 Advanced Actions: |
|
75 ----------------- |
|
76 |
|
77 Branch: |
|
78 Create a separate copy of the repo for private use (bug fixing, testing, etc). |
|
79 Diff/Change: |
|
80 Finding the differences between two versions of a file. |
|
81 Merge (or patch): |
|
82 Apply the changes from one branch to another, to bring it up-to-date. |
|
83 Conflict: |
|
84 When pending changes to a file contradict each other (both changes cannot be applied). |
|
85 |
|
86 Types of Version Control: |
|
87 ------------------------- |
|
88 |
|
89 (should we have this part at all?) |
|
90 Based on how source/code management is carried out in a tool there are two categories of Version Control Systems(VCS): |
|
91 |
|
92 - Centralized VCS: |
|
93 In this kind of system all the revision control functions are performed on a shared server. If two developers try to change the same file at the same time, without some method of managing access the developers may end up overwriting each others work. Centralized revision control systems solve this problem in one of two different "source management models": file locking and version merging. Both svn and cvs follows this kind of management. |
|
94 |
|
95 - Distributed VCS: |
|
96 In a distributed model, every developer has their own repo. Diffs, commits, and reverts are all done locally, one needs Internet only to share the changes with others. It makes work faster, handles branching and merging in better way, with less management. hg, bzr and git uses this work flow. |
|
97 |
|
98 Get Going with Hg: |
|
99 ================== |
|
100 |
|
101 Why hg? |
|
102 ------- |
|
103 |
73 |
104 - easy to learn and use. |
74 - easy to learn and use. |
105 - lightweight. |
75 - lightweight. |
106 - scales excellently. |
76 - scales excellently. |
107 - based on Python. |
77 - based on Python. |
108 |
78 |
109 A small point to notice here, hg cant track binary files for changes, one can add them to repo, but wont be able to track changes made to it. And hg considers, odt, pdf files as binary. |
79 Installation |
110 |
80 ------------ |
111 Installation: |
81 |
112 ------------- |
82 - For Linux based systems, hg is available in most of package management. So |
113 |
83 for say Ubuntu systems:: |
114 - For Linux based systems, hg is available in most of package management. So for say Ubuntu systems:: |
|
115 |
84 |
116 $ sudo apt-get install mercurial |
85 $ sudo apt-get install mercurial |
117 |
86 |
118 will be all you need to install hg. Similarly Fedora users can use yum to install hg. |
87 will be all you need to install hg. Similarly Fedora users can use yum to |
119 |
88 install hg. |
120 - For Windows and Mac OS X systems the setup can be downloaded from http://mercurial.selenic.com/downloads/ and standard installation can be followed. |
89 |
121 |
90 - For Windows and Mac OS X systems the setup can be downloaded from |
122 Getting Started: |
91 http://mercurial.selenic.com/downloads/ and standard installation can be |
|
92 followed. |
|
93 |
|
94 Just say ``hg`` in your shell, to see some of the commands that ``hg`` |
|
95 provides and say ``hg version`` to see the version of ``hg`` that has |
|
96 been installed on your system. |
|
97 |
|
98 Let there be Repository |
|
99 ======================= |
|
100 |
|
101 To start using Mercurial (or ``hg``) and get the benefits of using a version |
|
102 control system, we should first have a **repository**. A repository is a |
|
103 folder with all your files and a store of all the changes that were made to |
|
104 it. To save disk space, ``hg`` doesn't save all the files, but only saves |
|
105 only a series of changes made to the files. |
|
106 |
|
107 We have talked of an example of how we cook up our own version control |
|
108 systems. Mercurial does almost the same thing with one major difference. It |
|
109 doesn't keep track of individual files. It keeps snapshots of the whole |
|
110 directory (or repository), instead of individual files. |
|
111 |
|
112 A repository can either be started using an ``init`` command or an existing |
|
113 repository could be **cloned**. |
|
114 |
|
115 Let us look at creating our own repository, now. We can look at obtaining |
|
116 already existing repositories, at a later stage. |
|
117 |
|
118 Let's say we have a folder called ``book``, which has all the chapters of a |
|
119 book as text files. Let us convert that folder, into a ``hg`` repository. |
|
120 |
|
121 :: |
|
122 |
|
123 $ cd book/ |
|
124 $ ls -a |
|
125 . .. chapter1.txt chapter2.txt chapter3.txt |
|
126 $ |
|
127 |
|
128 We have three chapters in the folder. We convert this folder into a mercurial |
|
129 repository using the ``hg init`` command |
|
130 |
|
131 :: |
|
132 |
|
133 $ hg init |
|
134 $ ls -a |
|
135 . .. .hg chapter1.txt chapter2.txt chapter3.txt |
|
136 $ |
|
137 |
|
138 The ``.hg`` directory indicates that our book directory is now a ``hg`` |
|
139 repository. Mercurial keeps all the history of the changes made, and a few |
|
140 other config files, etc. in this directory. The directory, ``book`` is called |
|
141 our **working directory**. |
|
142 |
|
143 Adding Files |
|
144 ------------ |
|
145 |
|
146 We now have a fresh repository, but all our files are not being tracked or |
|
147 watched by ``mercurial``, yet. We need to explicitly ask it to watch the |
|
148 files, that we want it to. |
|
149 |
|
150 To see this use the ``hg status`` command. |
|
151 :: |
|
152 |
|
153 $ hg status |
|
154 ? chapter1.txt |
|
155 ? chapter2.txt |
|
156 ? chapter3.txt |
|
157 |
|
158 |
|
159 We see the three files for the chapters, but they are preceded by a ``?`` |
|
160 mark. What does it mean? |
|
161 |
|
162 We use the ``help`` command to see what this means. |
|
163 :: |
|
164 |
|
165 $ hg help status |
|
166 ... |
|
167 The codes used to show the status of files are: |
|
168 |
|
169 M = modified |
|
170 A = added |
|
171 R = removed |
|
172 C = clean |
|
173 ! = missing (deleted by non-hg command, but still tracked) |
|
174 ? = not tracked |
|
175 I = ignored |
|
176 = origin of the previous file listed as A (added) |
|
177 ... |
|
178 |
|
179 By looking at the codes, it is clear that our files are not *yet* being |
|
180 tracked by ``hg``. We now use the add command to ask ``hg`` to track these |
|
181 files. |
|
182 |
|
183 The ``status`` command gives the *status* of our working-directory at this |
|
184 point in time. Using this command after every ``hg`` command you use, is a |
|
185 good idea, at least until you are reasonably comfortable with the use of |
|
186 ``hg``. |
|
187 |
|
188 :: |
|
189 |
|
190 $ hg add |
|
191 adding chapter1.txt |
|
192 adding chapter2.txt |
|
193 adding chapter3.txt |
|
194 $ hg status |
|
195 A chapter1.txt |
|
196 A chapter2.txt |
|
197 A chapter3.txt |
|
198 $ |
|
199 |
|
200 This simply adds all the files in the (working) directory, to the repository. |
|
201 As expected, the ``status`` command shows an ``A`` before he file names. |
|
202 |
|
203 Taking Snapshots |
123 ---------------- |
204 ---------------- |
124 |
205 |
125 After installation is complete lets get started with using. First things first, lets pay our homage to *man* pages as per rituals: :: |
206 We have added a set of new files to the repository, but we haven't told |
126 |
207 mercurial to remember these changes, i.e., to take a snapshot at this point |
127 $ man hg |
208 in time. We do this by using the ``commit`` command. |
128 |
209 |
129 This will give us manuscript of all the options available with *hg*. We can either look through all of it, or a better way will be to use built-in help system of *hg*. Say to get brief list of all commands, along with a description of what each does we can use :: |
210 :: |
130 |
211 |
131 $ hg help |
212 $ hg commit |
132 |
213 |
133 Mercurial Distributed SCM |
214 We are now prompted with a new editor window. We type out our message here |
134 list of commands: |
215 describing the changes that we have made. |
135 add add the specified files on the next commit |
216 |
136 addremove ----------------------- |
217 :: |
137 ------------------------------------ |
218 |
138 heads show current repository heads or show branch heads |
219 Initial Commit |
139 ------------------------------------ |
220 |
140 |
221 HG: Enter commit message. Lines beginning with 'HG:' are removed. |
141 For specific command, just follow the command name after the help. :: |
222 HG: Leave message empty to abort commit. |
142 |
223 |
143 $ hg help diff |
224 Mercurial has now taken a snapshot of our repository and has attached our |
144 hg diff [OPTION]... [-r REV1 [-r REV2]] [FILE]... |
225 description along with it. To see the status of the files in the repository, |
145 |
226 use the ``hg status`` command. |
146 diff repository (or selected files) |
227 |
147 Show differences between revisions for the specified files. |
228 :: |
148 Differences between files are shown using the unified diff format. |
229 |
149 NOTE:____________ |
230 $ hg st |
150 |
231 $ |
151 Let there be Repository: |
232 |
152 ------------------------ |
233 The command does not return anything, when there are no uncommitted changes. |
153 |
234 Also, notice that I have started getting lazy and used only a short name |
154 In Mercurial, everything happens inside a repository. The repository for a project contains all of the files that “belong to” that project, along with a historical record of the project's files. A repository is simply a directory which Mercurial treats as special. |
235 ``st`` for the status command. Mercurial accepts short names, as long as they |
155 |
236 can be disambiguated (just like tab completion). |
156 There can be two ways to create a repo, either downloading a copy of existing repo available on Internet, or creating/starting a new repo. |
237 |
157 |
238 Viewing the History |
158 Say we have a directory which we want to bring under version control, so we start a new repository using *hg init*: :: |
239 ------------------- |
159 |
240 |
160 $ ls -a circulate/ |
241 To see the history of the changes to our repository, we use ``hg log``. We |
161 . .. lena.png pendulum.txt points.txt pos.txt sslc1.py sslc1.txt |
242 can view the change that we just made to our repository. |
162 $ cd circulate/ |
243 |
163 $ hg init |
244 :: |
164 $ ls -a |
245 |
165 . .. .hg lena.png pendulum.txt points.txt pos.txt sslc1.py sslc1.txt |
246 $ hg log |
166 |
247 changeset: 0:cbf6e2a375b4 |
167 *.hg* directory indicates that this new dir is now a repo.This is where Mercurial keeps all of its metadata for the repository.The contents of the .hg directory and its subdirectories are private to Mercurial. Rest all files are for the user to use them as they pleases. |
248 tag: tip |
168 |
249 user: punchagan@shrike.aero.iitb.ac.in |
169 For getting already existing repo hg uses command *"clone"* :: |
250 date: Fri Jan 28 14:04:07 2011 +0530 |
170 |
251 summary: Initial Commit |
171 $ hg clone http://hg.serpentine.com/tutorial/hello localCopyhello |
252 |
172 |
253 |
173 requesting all changes |
254 As we already discussed, mercurial keeps track of the changes that are made |
174 adding changesets |
255 to the files in the repository. Notice, that our ``log`` is showing a |
175 adding manifests |
256 **changeset**. A change set is nothing but a set of changes made to the |
176 adding file changes |
257 repository between two consecutive commits (the action of taking snapshots). |
177 added 5 changesets with 5 changes to 2 files |
258 Notice that ``hg`` also shows the date at which the commit was made and the |
178 updating working directory |
259 description of the changeset. |
179 2 files updated, 0 files merged, 0 files removed, 0 files unresolved |
260 |
180 |
261 User information |
181 If clone succeeded, there would be a local directory called localCopyhello, with some files: :: |
|
182 |
|
183 $ ls localCopyhello/ |
|
184 hello.c Makefile |
|
185 |
|
186 Every Mercurial repository is complete, self-contained, and independent. It contains its own private copy of a project's files and history. |
|
187 |
|
188 Creating a branch of existing local repo is very easy via hg using clone command: :: |
|
189 |
|
190 $ hg clone localCopyhello newCopy |
|
191 updating working directory |
|
192 2 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
193 |
|
194 newCopy is exact copy of already existing repo. These local branches can prove really handy at times. It allows keep multiple copies of local branch for different purposes, say for debugging, testing, working version. |
|
195 |
|
196 History or Logs: |
|
197 ---------------- |
262 ---------------- |
198 |
263 |
199 For the new repo created, first thing which can be tried is to check the logs/history. What changes were made and when and why, answers to all those questions are stored in logs safely. So for the cloned repo the history can be viewed using command *"log"* (following commands are wrt localCopyhello repo). :: |
264 But there is a slight problem with the user details that mercurial is saving. |
|
265 It saves my username with my machine name. It is a general good practice to |
|
266 use your full name with your email id. We set our username in the ``.hgrc`` |
|
267 file in our Home folder. (``$HOME/.hgrc`` on Unix like systems and |
|
268 ``%HOME%\.hgrc`` on Windows systems) |
|
269 |
|
270 We open the file in our favorite editor and add the username details. |
|
271 |
|
272 :: |
|
273 |
|
274 $ emacs ~/.hgrc |
|
275 [ui] |
|
276 username = Puneeth Chaganti <punchagan@fossee.in> |
|
277 |
|
278 We have now set the username details for mercurial to use, in all our future |
|
279 commits. (Note: You can also set user preferences at the repository level. |
|
280 Exercise-N asks you to do that) |
|
281 |
|
282 Let us now make another commit to see if this has taken effect. Let us |
|
283 add author information to all the chapters that we have. |
|
284 |
|
285 :: |
|
286 |
|
287 Author: Puneeth Chaganti <punchagan@fossee.in> |
|
288 |
|
289 |
|
290 Once we have added this to all the files, let us commit this change. We again |
|
291 used the ``hg commit`` command to commit the changes that we have made. |
|
292 |
|
293 :: |
|
294 |
|
295 $ hg commit |
|
296 |
|
297 We are again prompted with the editor window to enter our commit message and |
|
298 we type out our commit message. There are some good practices when typing out |
|
299 a commit message too. It is a general practice to have a summary line in the |
|
300 commit message which is no longer than 60 to 65 characters giving a summary |
|
301 of the change we have made. This is followed up with an explanation of why |
|
302 this was changed, what is the effect of this change, known bugs/issues |
|
303 remaining, if any, etc. |
|
304 |
|
305 :: |
|
306 |
|
307 Add author info to all the chapters |
|
308 |
|
309 All the chapters must have an author info. Added Puneeth Chaganti |
|
310 as the author. New authors can be added in newlines. |
|
311 |
|
312 HG: Enter commit message. Lines beginning with 'HG:' are removed. |
|
313 HG: Leave message empty to abort commit. |
|
314 |
|
315 ``hg log`` should now show us both the changes that we have made. Notice that |
|
316 the username settings are being used and also, the summary of the changeset |
|
317 shows only the first line in the description that we have added. Also, notice |
|
318 that ``hg`` shows the commits in the reverse chronological order, which is |
|
319 useful. |
|
320 |
|
321 Mercurial Magic |
|
322 =============== |
|
323 |
|
324 You must already be wondering, why we need all the overhead of |
|
325 ``commit`` and ``log``, etc. What is all this fuss about? "Isn't it |
|
326 just a waste of time?" |
|
327 |
|
328 Reverting Changes |
|
329 ----------------- |
|
330 |
|
331 While you were wondering, let's say your friend walks in and together you |
|
332 make a lot of changes. |
|
333 |
|
334 1. You replace all the occurrences of ``&`` in ``chapter1.txt`` with |
|
335 ``and``. |
|
336 2. You delete the ``chapter3.txt`` file. |
|
337 |
|
338 :: |
|
339 |
|
340 $ rm chapter3.txt |
|
341 $ hg st |
|
342 M chapter1.txt |
|
343 ! chapter3.txt |
|
344 $ |
|
345 |
|
346 |
|
347 But after a while, you realize that these changes are unwarranted. You |
|
348 want to go back to the previous state, undoing all the changes that |
|
349 you made, after your friend arrived. |
|
350 |
|
351 The undo in your editor may allow undoing the first change (if you |
|
352 haven't closed it after making the changes) but there's no way you |
|
353 could get back your ``chapter3.txt`` file, using your editor. But |
|
354 don't worry. Mercurial to the rescue! |
|
355 |
|
356 We shall use the ``revert`` command of ``hg`` to undo all the changes |
|
357 after the last commit. As we want to undo all the changes, we use the |
|
358 ``revert`` command with the ``--all`` argument. |
|
359 |
|
360 :: |
|
361 |
|
362 $ hg revert --all |
|
363 reverting chapter1.txt |
|
364 reverting chapter3.txt |
|
365 $ hg st |
|
366 ? chapter1.txt.orig |
|
367 $ ls |
|
368 chapter1.txt chapter1.txt.orig chapter2.txt chapter3.txt |
|
369 |
|
370 As you can see the ``chapter3.txt`` file has been restored. But ``hg`` |
|
371 gives you a new file ``chapter1.txt.orig``. Mercurial actually doesn't |
|
372 like to delete any of the changes that you have made. So, it makes a |
|
373 back-up of the file ``chapter1.txt`` in the present state and gives |
|
374 you back the old file. |
|
375 |
|
376 If we now decide, that we want to ``redo`` the changes that we had |
|
377 done to the ``chapter1``, we can just overwrite the ``chapter1.txt`` |
|
378 file with the backed up file. |
|
379 :: |
|
380 |
|
381 $ mv chapter1.txt.orig chapter1.txt |
|
382 $ hg st |
|
383 M chapter1.txt |
|
384 $ |
|
385 |
|
386 Viewing Changes |
|
387 --------------- |
|
388 |
|
389 Let's say we now want to ``commit`` these changes, but we are not sure |
|
390 of all the changes that we have made to the file, since it's been a |
|
391 while after we made the changes. We could use the ``diff`` command to |
|
392 see all the changes that have been made in the file. |
|
393 |
|
394 :: |
|
395 |
|
396 $ hg diff |
|
397 diff -r 3163b8db10bb chapter1.txt |
|
398 --- a/chapter1.txt Fri Jan 28 16:21:29 2011 +0530 |
|
399 +++ b/chapter1.txt Fri Jan 28 16:22:41 2011 +0530 |
|
400 @@ -8,9 +8,9 @@ |
|
401 1 Session |
|
402 Table of Contents |
|
403 ================= |
|
404 -1 Introduction & Motivation |
|
405 -2 Creating & Getting repositories |
|
406 +1 Introduction and Motivation |
|
407 +2 Creating and Getting repositories |
|
408 3 Revision history |
|
409 -4 Making & sharing changes |
|
410 -5 Merges & Conflicts |
|
411 +4 Making and sharing changes |
|
412 +5 Merges and Conflicts |
|
413 |
|
414 You see some cryptic output, but it's essentially giving you the list |
|
415 of changes made to the file. All the lines that were deleted are |
|
416 preceded by a ``-`` and all the new-lines are preceded by a ``+``. You |
|
417 can see that the ``&`` occurrences have been replaces with ``and``. |
|
418 |
|
419 Let us now commit this change. |
|
420 :: |
|
421 |
|
422 $ hg commit |
|
423 |
|
424 Replace all occurrences of & with and |
|
425 |
|
426 On the suggestion of Madhusudan C S. |
|
427 |
|
428 HG: Enter commit message. Lines beginning with 'HG:' are removed. |
|
429 HG: Leave message empty to abort commit. |
|
430 |
|
431 :: |
|
432 |
|
433 $ hg log |
|
434 |
|
435 We can see the history of all the commits that we have made in our |
|
436 project. As you can see, the logs have started getting longer (and |
|
437 hence have been dropped from the output) and may even be getting out |
|
438 of our screens. Also, we are not very interested in all the commits in |
|
439 the project. We usually want to see the last few commits. |
|
440 |
|
441 Revision Numbering |
|
442 ------------------ |
|
443 |
|
444 Let us now see how to get logs of specific commits and a range of |
|
445 commits. Have a look at the logs that the previous ``log`` command has |
|
446 printed and look at the ``changeset`` line. It shows a number followed |
|
447 by a semi-colon and some long hexa-decimal string. The number is |
|
448 called the **revision number**. It is an identifier for the commit, |
|
449 and can be along with various commands to specify the revision number, |
|
450 if required. |
|
451 |
|
452 Let us now check the logs of the very first commit of the project. |
|
453 :: |
|
454 |
|
455 $ hg log -r0 |
|
456 changeset: 0:cbf6e2a375b4 |
|
457 tag: tip |
|
458 user: punchagan@shrike.aero.iitb.ac.in |
|
459 date: Fri Jan 28 14:04:07 2011 +0530 |
|
460 summary: Initial Commit |
|
461 |
|
462 Now, if we wish to get the logs of the latest commit only, how do we |
|
463 do it? We could specify the exact revision number of the commit (2) or |
|
464 just use -1 to start counting in the reverse chronological order. |
|
465 :: |
|
466 |
|
467 $ hg log -r-1 |
|
468 changeset: 2:98f7f4a1bb4d |
|
469 tag: tip |
|
470 user: Puneeth Chaganti <punchagan@fossee.in> |
|
471 date: Fri Jan 28 16:24:42 2011 +0530 |
|
472 summary: Replace all occurrences of & with and |
|
473 |
|
474 You could also specify a range of commits whose logs you would like to |
|
475 see. Say, we would like to see the last two commits, |
|
476 :: |
|
477 |
|
478 $ hg log -r-1:-2 |
|
479 |
|
480 This is equivalent to using the following |
|
481 :: |
|
482 |
|
483 $ hg log -r2:1 |
|
484 |
|
485 You could also see the changes made to a particular file, in the |
|
486 specified range of the commits. Say, we wish to see the changes made |
|
487 to the ``chapter2.txt`` file in the last two commits. |
|
488 :: |
|
489 |
|
490 $ hg log -r-1:-2 chapter2.txt |
|
491 changeset: 1:3163b8db10bb |
|
492 user: Puneeth Chaganti <punchagan@fossee.in> |
|
493 date: Fri Jan 28 16:21:29 2011 +0530 |
|
494 summary: Add author info to all the chapters |
|
495 |
|
496 Notice that it shows only the logs of revision 1, since no changes |
|
497 were made to the specified file in the second commit. |
|
498 |
|
499 You can do all of this with the ``diff`` command to see the exact |
|
500 changes made to the files, instead of seeing the ``log`` message. This |
|
501 will be a part of your exercises. |
|
502 |
|
503 Collaborating with Mercurial |
|
504 ============================ |
|
505 |
|
506 When motivating the use of version control systems, we spoke a lot about |
|
507 collaboration and sharing our changes with our peers. Let us now see how we |
|
508 can share our project with our peers and collaborate with them. |
|
509 |
|
510 Cloning Repositories |
|
511 -------------------- |
|
512 |
|
513 For this purpose let us create a central repository, a copy of our |
|
514 repository, which is different from the one in which we are working. The |
|
515 ``clone`` command is used to **clone** or replicate an existing repository. |
|
516 |
|
517 :: |
|
518 |
|
519 $ hg clone book book-repo |
|
520 |
|
521 This creates a copy of our repository, ``book``, with the name ``book-repo``. |
|
522 The syntax of the ``clone`` command is -- ``hg clone SOURCE [DEST]``, where |
|
523 the optional argument DEST is being represented in brackets. Here we are |
|
524 giving book-repo as the destination. |
|
525 |
|
526 The clone command can be used to replicate already existing repositories, |
|
527 either on your own machine or on some remote machine somewhere on the |
|
528 network. Since, ``hg`` maintains a copy of the full repository with every |
|
529 copy of the repository, the two copies that we have are exactly equivalent. |
|
530 |
|
531 ``book-repo`` is the repository we shall be using as a central repository |
|
532 and share it with our peers. |
|
533 |
|
534 Sharing Repositories |
|
535 -------------------- |
|
536 |
|
537 A mercurial repository can be shared in multiple ways. We shall use the |
|
538 ``http`` protocol to share the repository. Mercurial comes inbuilt with a |
|
539 tiny server that can be used to share your repository over the network. To |
|
540 start sharing the repository, we say |
|
541 |
|
542 :: |
|
543 |
|
544 $ cd ../book-repo |
|
545 $ hg serve |
|
546 |
|
547 This will start serving the repository on the network on the port 8000. |
|
548 Anybody in your network can access the repository in their browsers. Let us |
|
549 see how it looks, in our own browser. We open the url `http://localhost:8000` |
|
550 in our browser. |
|
551 |
|
552 Let's say, our friend Madhu, now wants to clone this repository. He will use |
|
553 our ip-address and the port on which we are serving the repository, to clone |
|
554 the repository. Instead of using two machines, for the purposes of |
|
555 demonstration, we shall clone into our own machine, with a different name. |
|
556 |
|
557 :: |
|
558 |
|
559 $ hg clone http://192.168.1.101:8000 book-madhu |
|
560 |
|
561 This will clone the repository to the folder, ``book-madhu``. The log of the |
|
562 repository will, obviously, be the same as our original repository. |
|
563 |
|
564 :: |
200 |
565 |
201 $ hg log |
566 $ hg log |
202 changeset: 4:2278160e78d4 |
567 |
|
568 Sharing Changes |
|
569 --------------- |
|
570 |
|
571 Let's say, Madhu now makes some changes to the repository. |
|
572 |
|
573 1. He adds his name to the Authors list. |
|
574 2. He moves down the Getting repositories part into a different section. |
|
575 |
|
576 :: |
|
577 |
|
578 $ hg diff |
|
579 diff -r 98f7f4a1bb4d chapter1.txt |
|
580 --- a/chapter1.txt Fri Jan 28 16:24:42 2011 +0530 |
|
581 +++ b/chapter1.txt Fri Jan 28 23:03:37 2011 +0530 |
|
582 @@ -2,6 +2,7 @@ |
|
583 ======================= |
|
584 |
|
585 Author: Puneeth Chaganti <punchagan@fossee.in> |
|
586 + Madhusudan CS <madhusudancs@fossee.in> |
|
587 Date: 2011-01-28 13:58:47 IST |
|
588 |
|
589 |
|
590 @@ -9,8 +10,9 @@ |
|
591 Table of Contents |
|
592 ================= |
|
593 1 Introduction and Motivation |
|
594 -2 Creating and Getting repositories |
|
595 +2 Creating |
|
596 3 Revision history |
|
597 4 Making and sharing changes |
|
598 -5 Merges and Conflicts |
|
599 +5 Getting repositories |
|
600 +6 Merges and Conflicts |
|
601 $ |
|
602 |
|
603 He then commits these changes and **pushes** them to the central repository |
|
604 that we have created. |
|
605 |
|
606 :: |
|
607 |
|
608 $ hg commit |
|
609 $ hg push |
|
610 pushing to http://192.168.1.101:8000 |
|
611 searching for changes |
|
612 ssl required |
|
613 |
|
614 The push failed, obviously, since we have not taken care of access rights |
|
615 etc. It doesn't make much sense to allow anybody to make changes to a public |
|
616 repository, by default. We will need to make changes to the settings of the |
|
617 repository to allow this. **Note**: This is obviously not a safe way to share |
|
618 your repository, but for our purposes, this is sufficient. |
|
619 |
|
620 We add the following lines to the ``.hg/hgrc`` of the ``book-repo`` |
|
621 repository. |
|
622 :: |
|
623 |
|
624 [web] |
|
625 push_ssl=False |
|
626 allow_push=* |
|
627 |
|
628 This will allow anybody to push to the repository, now. |
|
629 |
|
630 Madhusudan can now push and his changes will appear in the central |
|
631 repository. |
|
632 |
|
633 :: |
|
634 |
|
635 $ hg push |
|
636 |
|
637 Let's confirm it in the web interface that we started with the ``hg serve`` |
|
638 command. |
|
639 |
|
640 Pulling Changes |
|
641 --------------- |
|
642 |
|
643 Let us now **pull** these changes into our original repository ``book`` that |
|
644 we have been working with. Before pulling the changes, we can use the command |
|
645 ``hg incoming`` to see the changes that have been made to the repository |
|
646 after our last **pull** and the changesets that will be coming into our |
|
647 repository after we do a **pull**. |
|
648 |
|
649 :: |
|
650 |
|
651 $ hg incoming |
|
652 abort: repository default not found! |
|
653 |
|
654 What is going on here? This is because, we didn't clone our repository |
|
655 ``book`` from the central repository ``book-repo``. We can now add the |
|
656 location of the central repository to the ``hgrc`` file, of this project. |
|
657 |
|
658 :: |
|
659 |
|
660 [paths] |
|
661 default = /home/punchagan/book-repo |
|
662 |
|
663 Now, we can check the incoming changes. |
|
664 |
|
665 :: |
|
666 |
|
667 $ hg incoming |
|
668 searching for changes |
|
669 changeset: 3:3cd54926dbea |
203 tag: tip |
670 tag: tip |
204 user: Bryan O'Sullivan <bos@serpentine.com> |
671 user: Madhusudan CS <madhusudancs@fossee.in> |
205 date: Sat Aug 16 22:16:53 2008 +0200 |
672 date: Fri Jan 28 23:08:25 2011 +0530 |
206 summary: Trim comments. |
673 summary: Add my name to authors and move getting repositories section |
207 |
674 to 5 |
208 changeset: 3:0272e0d5a517 |
675 |
209 user: Bryan O'Sullivan <bos@serpentine.com> |
676 |
210 date: Sat Aug 16 22:08:02 2008 +0200 |
677 To now **pull** these changes, we use the ``pull`` command. |
211 summary: Get make to generate the final binary from a .o file. |
678 |
212 |
679 :: |
213 changeset: 2:fef857204a0c |
680 |
214 user: Bryan O'Sullivan <bos@serpentine.com> |
681 $ hg pull |
215 date: Sat Aug 16 22:05:04 2008 +0200 |
682 pulling from /home/punchagan/book-repo |
216 summary: Introduce a typo into hello.c. |
|
217 |
|
218 changeset: 1:82e55d328c8c |
|
219 user: mpm@selenic.com |
|
220 date: Fri Aug 26 01:21:28 2005 -0700 |
|
221 summary: Create a makefile |
|
222 |
|
223 changeset: 0:0a04b987be5a |
|
224 user: mpm@selenic.com |
|
225 date: Fri Aug 26 01:20:50 2005 -0700 |
|
226 summary: Create a standard "hello, world" program |
|
227 |
|
228 By default, this command prints a brief paragraph of output for each change to the project that was recorded.The fields in a record of output from hg log are as follows: |
|
229 |
|
230 - changeset: This field is a identifier for the changeset. The hex string is a unique identifier. |
|
231 - user: The identity of the person who created the changeset. |
|
232 - date: The date and time on which the changeset was created. |
|
233 - summary: The first line of the text message entered to describe the changeset. |
|
234 |
|
235 To narrow the output of hg log down to a single revision, use the -r option. :: |
|
236 |
|
237 $ hg log -r 3 |
|
238 changeset: 3:0272e0d5a517 |
|
239 user: Bryan O'Sullivan <bos@serpentine.com> |
|
240 date: Sat Aug 16 22:08:02 2008 +0200 |
|
241 summary: Get make to generate the final binary from a .o file. |
|
242 |
|
243 *range notation* can be used to get history of several revisions without having to list each one. :: |
|
244 |
|
245 $ hg log -r 2:4 |
|
246 changeset: 2:fef857204a0c |
|
247 user: Bryan O'Sullivan <bos@serpentine.com> |
|
248 date: Sat Aug 16 22:05:04 2008 +0200 |
|
249 summary: Introduce a typo into hello.c. |
|
250 |
|
251 changeset: 3:0272e0d5a517 |
|
252 user: Bryan O'Sullivan <bos@serpentine.com> |
|
253 date: Sat Aug 16 22:08:02 2008 +0200 |
|
254 summary: Get make to generate the final binary from a .o file. |
|
255 |
|
256 changeset: 4:2278160e78d4 |
|
257 tag: tip |
|
258 user: Bryan O'Sullivan <bos@serpentine.com> |
|
259 date: Sat Aug 16 22:16:53 2008 +0200 |
|
260 summary: Trim comments. |
|
261 |
|
262 -v option with "log" gives some extra details related to a changeset. |
|
263 |
|
264 Making Changes: |
|
265 --------------- |
|
266 |
|
267 Lets follow a simple exercise of *managing letters* using hg. We create a new directory and start revision tracking on it.:: |
|
268 |
|
269 $ mkdir letter |
|
270 $ cd letter |
|
271 $ touch letter.tex |
|
272 $ hg init |
|
273 |
|
274 Now lets try to create a local clone of this repository:: |
|
275 |
|
276 $ hg clone letter letter-clone |
|
277 updating working directory |
|
278 0 files updated, 0 files merged, |
|
279 0 files removed, 0 files unresolved |
|
280 |
|
281 So here, message says 0 files updated but we have just created a *tex* file inside it. Lets try to see status of our main repository by using *status(st)* command:: |
|
282 |
|
283 $ cd letter |
|
284 $ hg st |
|
285 ? letter.tex |
|
286 |
|
287 "?" sign in front of file indicates that this file is alien to hg, as in we have to *add* it to repo by:: |
|
288 |
|
289 $ hg add letter.tex |
|
290 $ hg st |
|
291 A letter.tex |
|
292 |
|
293 So file is now part of repository(A symbol). We *commit (alias ci)* it to repo and make changes effective :: |
|
294 |
|
295 $ hg ci -u "Shantanu <shantanu@fossee.in>" |
|
296 -m "First commit." |
|
297 $ hg log |
|
298 changeset: 0:210664b4ed58 |
|
299 tag: tip |
|
300 user: Shantanu <shantanu@fossee.in> |
|
301 date: Tue Feb 23 19:41:45 2010 +0530 |
|
302 summary: First commit. |
|
303 |
|
304 Some arguments passed to *ci* command are worth noticing: |
|
305 - *u* is to provide name and email contact information of person making changes! |
|
306 - *m* is to provide one-line summary of changeset. |
|
307 |
|
308 If we don't give these options, *ci* will take us to a default editor, there we have to specify a commit *message* in first line, then we can edit other information like username, once done just exit the editor and changes are committed to the repo. Now these changes will be visible in logs. |
|
309 |
|
310 Similar to add there are other commands available for file management in repo. *copy (alias cp)* command is used to mark files as copied for the next commit. :: |
|
311 |
|
312 $ hg cp letter.tex letter-prof.tex |
|
313 |
|
314 *rename(alias mv)* rename files; equivalent of copy + remove. :: |
|
315 |
|
316 $ hg rename letter.tex letter-personal.tex |
|
317 $ hg st |
|
318 A letter-personal.tex |
|
319 A letter-pro.tex |
|
320 R letter.tex |
|
321 $ hg ci -u "Shantanu <shantanu@fossee.in>" -m "Renamed and added letters." |
|
322 |
|
323 *tip* command shows newest revision in the repository. :: |
|
324 |
|
325 $ hg tip |
|
326 changeset: 1:4a2d973a92de |
|
327 user: Shantanu <shantanu@fossee.in> |
|
328 date: Tue Feb 23 19:50:39 2010 +0530 |
|
329 summary: Renamed and added letters. |
|
330 |
|
331 Sharing Changes: |
|
332 ---------------- |
|
333 |
|
334 Pulling from repo: |
|
335 ~~~~~~~~~~~~~~~~~~ |
|
336 |
|
337 As mentioned earlier that repositories in Mercurial are self-contained. This means that the changeset just created exists only in *letter* repository and not in previously cloned . There are a few ways that can be used to propagate this change into other repositories. *pull* command will download all changeset from main repo. :: |
|
338 |
|
339 $ cd letter-clone |
|
340 $ hg pull |
|
341 pulling from /home/baali/letter |
|
342 requesting all changes |
|
343 adding changesets |
|
344 adding manifests |
|
345 adding file changes |
|
346 added 2 changesets with 2 changes to 2 files |
|
347 (run 'hg update' to get a working copy) |
|
348 |
|
349 *changeset* means a list of changes made to a file. In words of *hg help*, pull command is: :: |
|
350 |
|
351 pull changes from the specified source |
|
352 |
|
353 Pull changes from a remote repository to a local one. |
|
354 |
|
355 This finds all changes from the repository at the specified path |
|
356 or URL and adds them to the local repository. By default, this |
|
357 does not update the copy of the project in the working directory. |
|
358 |
|
359 Some times, even before pulling changesets, one may need to see what changes would be pulled, Mercurial provides *hg incoming* to tell what changes *hg pull* would pull into repo, without actually pulling the changes. This command is really handy in case of avoiding unwanted changesets into the repo. |
|
360 |
|
361 As output of *pull* command suggests it does not(by default) update the working directory. By update we mean, content of files and directory structure still remains the same as prior to *pull* command. *hg up (alias update)* command updates repo by adding latest imported changesets and bringing it upto date. :: |
|
362 |
|
363 $ ls -a |
|
364 . .. .hg |
|
365 $ hg up |
|
366 2 files updated, 0 files merged, |
|
367 0 files removed, 0 files unresolved |
|
368 $ ls -a |
|
369 . .. .hg letter-personal.tex |
|
370 letter-pro.tex |
|
371 |
|
372 To update to specific version, give a version number to the *hg update* command. |
|
373 |
|
374 Making Changes: |
|
375 ~~~~~~~~~~~~~~~ |
|
376 |
|
377 Lets start with adding content to letters. For start personal letter can be a letter to ask a boy/girl out! Using LaTeX to write letter, it would be straight forward, open the file in any text editor and add the following content to it :: |
|
378 |
|
379 \documentclass{letter} |
|
380 \begin{document} |
|
381 \begin{letter}{} |
|
382 \opening{Hello xxxxxx,} |
|
383 I really enjoyed meeting you in CS 101, |
|
384 but would love to know you better. |
|
385 How about a coffee on Thursday after class? |
|
386 \closing{-xxxxx} |
|
387 \end{letter} |
|
388 \end{document} |
|
389 |
|
390 Replace "xxxxx" with proper names to suite yourself. Mercurial's hg status command will tell us what Mercurial knows about the files in the repository. 'M' sign in front of feviStick.py indicates that Mercurial has noticed change(modified). :: |
|
391 |
|
392 $ hg st |
|
393 M letter-personal.tex |
|
394 |
|
395 At times more information is needed on knowing exactly what changes were made to what files. To do this, use the *hg diff* command. :: |
|
396 |
|
397 $ hg diff |
|
398 diff -r 4a2d973a92de letter-personal.tex |
|
399 --- a/letter-personal.tex Tue Feb 23 19:50:39 2010 +0530 |
|
400 +++ b/letter-personal.tex Tue Jun 08 16:12:19 2010 +0530 |
|
401 @@ -0,0 +1,11 @@ |
|
402 +\documentclass{letter} |
|
403 +\begin{document} |
|
404 + |
|
405 +\begin{letter}{} |
|
406 +\opening{Hello Jas,} |
|
407 + |
|
408 +I really enjoyed meeting you in CS 101, but would love to know you better. How about a coffee on Thursday after class? |
|
409 + |
|
410 +\closing{-Samarth} |
|
411 +\end{letter} |
|
412 +\end{document} |
|
413 |
|
414 We can modify files, build and test our changes, and use hg status and hg diff to review our changes, until we're satisfied with what we've done and arrive at a natural stopping point where we want to record our work in a new changeset. All the diffs prior to committing the changes would be done wrt earlier marked record.Then we use *hg commit* to create a new changeset |
|
415 |
|
416 Mercurial records your name and email-address with each change that you commit, so that you and others will later be able to tell who made each change. It also tries to automatically figure out a sensible username to commit the change with. When we try to use *hg commit* there are various ways by which one can specify User name, some of those are: |
|
417 |
|
418 - Specify a -u option to the hg commit command on the command line, followed by a username, this is the procedure we used earlier. |
|
419 - set HGUSER environment variable:: |
|
420 |
|
421 $ export HGUSER="xxxxx" |
|
422 - Edit hgrc file present in .hg folder to set this property, add following lines to that file and Mercurial will read those parameters from that location. :: |
|
423 |
|
424 [ui] |
|
425 username = Firstname Lastname <email.address@example.net> |
|
426 |
|
427 For me the hgrc file for *letter* clone repo looks like this: :: |
|
428 |
|
429 [paths] |
|
430 default = /home/baali/letter |
|
431 [ui] |
|
432 username = Shantanu Choudhary <shantanu@fossee.in> |
|
433 |
|
434 Once this parameter is set, *hg commit* command drops us into a text editor, to enter a message that will describe the modifications we've made in this changeset. This is called the commit message. It will be a record for readers of what we did and why, and it will be printed by hg log after we've finished committing. :: |
|
435 |
|
436 Added content to personal letter. |
|
437 HG: Enter commit message. Lines beginning with 'HG:' are removed. |
|
438 HG: -- |
|
439 HG: user: Shantanu Choudhary <shantanu@fossee.in> |
|
440 HG: branch 'default' |
|
441 HG: changed letter-personal.tex |
|
442 |
|
443 This would be your default system editor(for me it is vim, one can set it also), where you can enter the log message in first line, once you are done with log message quit the editor using *[ESC] key ":wq"*.Once we've finished the commit, we can use the hg tip command to display the changeset we just created. :: |
|
444 |
|
445 $ hg tip |
|
446 changeset: 2:a5d8cb2fac01 |
|
447 user: Shantanu <shantanu@fossee.in> |
|
448 date: Tue Feb 23 20:34:12 2010 +0530 |
|
449 summary: Added content to personal letter. |
|
450 |
|
451 One can do above mentioned procedure using following one line command: :: |
|
452 |
|
453 $ hg ci -u "Shantanu <shantanu@fossee.in>" -m "Added content to personal letter." |
|
454 |
|
455 Sharing Changes: |
|
456 ~~~~~~~~~~~~~~~~ |
|
457 |
|
458 So now we have this *letter-clone* repo where we created above changes and committed them. But the main repo(*trunk*) that is *letter* wont be hinted of these changes. It will be still in older stage, same way as we pulled changes to this cloned repo from main branch at starting. To share changes from a cloned repo to main branch hg provides with *push* command. It is same as *pull* but instead of pulling it pushes the changes to trunk. :: |
|
459 |
|
460 $ hg push ../Fevicol |
|
461 pushing to ../Fevicol |
|
462 searching for changes |
683 searching for changes |
463 adding changesets |
684 adding changesets |
464 adding manifests |
685 adding manifests |
465 adding file changes |
686 adding file changes |
466 added 1 changesets with 1 changes to 1 files |
687 added 1 changesets with 1 changes to 1 files |
467 |
688 (run 'hg update' to get a working copy) |
468 Same as with hg pull, the hg push command populates the changesets nothing more. :: |
689 |
469 |
690 |
470 $ cd ../letter |
691 *Note* that ``hg`` is giving us a message, asking us to run a ``hg update`` |
471 $ hg tip |
692 to get a working copy. Let us try to understand what this is. |
472 changeset: 2:a5d8cb2fac01 |
693 |
473 user: Shantanu <shantanu@fossee.in> |
694 As already explained, ``.hg`` folder has all the information about the |
474 date: Tue Feb 23 20:34:12 2010 +0530 |
695 changesets of the repository. When we do a ``pull`` the changesets from the |
475 summary: Added content to personal letter. |
696 remote repository are pulled to our repository, but our working directory is |
476 |
697 not affected by these changes. To see this, we could use the ``hg parent`` |
477 The branch where changes are being pushed still need *up* to be updated or for inclusion of all the imported changesets :: |
698 command. |
478 |
699 |
479 $ hg up |
700 :: |
480 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
701 |
481 $ cat letter-personal.tex |
702 $ hg parent |
482 \documentclass{letter} |
703 changeset: 2:98f7f4a1bb4d |
483 \begin{document} |
704 user: Puneeth Chaganti <punchagan@fossee.in> |
484 \begin{letter}{} |
705 date: Fri Jan 28 16:24:42 2011 +0530 |
485 \opening{Hello xxxx,} |
706 summary: Replace all occurrences of & with and |
486 I really enjoyed meeting you in CS 101, but would love to know you better. How about a coffee on Thursday after class? |
707 $ |
487 |
708 |
488 \closing{-xxxx} |
709 As we can see, the parent is still our last commit, and the changes made by |
489 \end{letter} |
710 Madhusudan are still not in our working directory. To get these changes we do |
490 \end{document} |
711 the update as suggested by ``hg``. |
491 |
712 |
492 Merging the Work: |
713 :: |
493 ~~~~~~~~~~~~~~~~~ |
714 |
494 |
715 $ hg up |
495 This is next aspect of any version control, how to merge work done by various participants of project in a way that no one looses changes being made, and still remains updated. Here is simple case study which can help understanding why merging is required: |
716 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
496 |
717 $ hg parent |
497 Two persons, A and B are contributing on same project. Both starts from cloning the same online repo(lets say present state X), so that both have a working local repo. Now A edits one of file, commits the changes and pushes to the repo, hence changing the state of repo to Y, but B, have not updated his repo, makes a change in one of files and reaches to a different state Z. Now when A pulls repo from B, his repo will have multiple heads. This stage is clearly ambiguous, the repo of A is not consistent, it has multiple heads, and from here, whatever changes he makes can take whatsoever direction if it is not fixed, and hence A will have to merge changes so that everything becomes consistent again. |
718 changeset: 3:3cd54926dbea |
498 |
719 tag: tip |
499 Lets see how this work with working repo, we will use letter and letter-clone repositories created earlier. For now, the status of both repo is: :: |
720 user: Madhusudan CS <madhusudancs@fossee.in> |
500 |
721 date: Fri Jan 28 23:08:25 2011 +0530 |
501 $ cd letter-clone |
722 summary: Add my name to authors and move getting repositories section |
502 $ hg tip |
723 to 5 |
503 changeset: 2:a5d8cb2fac01 |
724 $ |
504 user: Shantanu <shantanu@fossee.in> |
|
505 date: Tue Feb 23 20:34:12 2010 +0530 |
|
506 summary: Added content to personal letter. |
|
507 |
|
508 We share(clones) this repo with a friend, he goes through the letter and just makes small change of adding color to clogins part of letter. :: |
|
509 |
|
510 $ hg diff |
|
511 diff -r 4a2d973a92de letter-personal.tex |
|
512 --- a/letter-personal.tex Tue Feb 23 19:50:39 2010 +0530 |
|
513 +++ b/letter-personal.tex Wed Feb 24 12:03:33 2010 +0530 |
|
514 @@ -0,0 +1,12 @@ |
|
515 \documentclass{letter} |
|
516 +\usepackage{color} |
|
517 \begin{document} |
|
518 . |
|
519 -\closing{-Samarth} |
|
520 +\closing{\textcolor{red}{-Samarth}} |
|
521 |
|
522 Here the "-" sign shows which lines are removed, and "+" indicates what lines are added. He is satisfied and commits the changes. :: |
|
523 |
|
524 $ hg ci -u "Vattam <vattam@fossee.in>" -m "Added some suggestions." |
|
525 changeset: 3:71fd776d856b |
|
526 parent: 2:a5d8cb2fac01 |
|
527 user: Vattam <vattam@fossee.in> |
|
528 date: Wed Feb 24 12:54:31 2010 +0530 |
|
529 summary: Added some suggestions. |
|
530 |
|
531 In the meanwhile, it seems, our "xxxx" is already dating someone else. So we also change the name to "yyyy" who is available, and we commit it :: |
|
532 |
|
533 $ cd letter |
|
534 $ hg ci -u "Shantanu <shantanu@fossee.in>" -m "Changed name." |
|
535 $ hg tip |
|
536 changeset: 3:02b49a53063f |
|
537 user: Shantanu <shantanu@fossee.in> |
|
538 date: Wed Feb 24 13:12:26 2010 +0530 |
|
539 summary: Changed name. |
|
540 |
725 |
541 So now we have two repo, who have different commit history and tree. |
726 As expected the **update** command updates the parent to the latest changes |
542 |
727 that we just pulled from the remote repository. |
543 .. image:: glog-main.png |
728 |
544 |
729 The update command can also be used to go back into an older revision, by |
545 .. image:: glog-suggestion.png |
730 specifying the revision to which we want to go to. |
546 |
731 |
547 If we try to pull changes from one to another, this is how it goes(we are still in letter repo): :: |
732 :: |
548 |
733 |
549 $ hg pull ../letter-suggestion |
734 $ hg up -r1 |
550 pulling from ../letter-suggestion |
735 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
736 $ hg parent |
|
737 changeset: 1:3163b8db10bb |
|
738 user: Puneeth Chaganti <punchagan@fossee.in> |
|
739 date: Fri Jan 28 16:21:29 2011 +0530 |
|
740 summary: Add author info to all the chapters |
|
741 $ hg cat chapter1.txt |
|
742 # Displays the contents of the chapter1.txt file as in revision 1. |
|
743 |
|
744 To return to the latest revision we just use the ``up`` or ``update`` command |
|
745 without specifying any revision number. |
|
746 |
|
747 :: |
|
748 |
|
749 $ hg up |
|
750 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
751 $ hg parent |
|
752 changeset: 3:3cd54926dbea |
|
753 tag: tip |
|
754 user: Madhusudan CS <madhusudancs@fossee.in> |
|
755 date: Fri Jan 28 23:08:25 2011 +0530 |
|
756 summary: Add my name to authors and move getting repositories section |
|
757 to 5 |
|
758 $ |
|
759 |
|
760 Simultaneous Changes |
|
761 -------------------- |
|
762 |
|
763 Ok, we have been talking about collaboration, but this is a nice situation, |
|
764 where I was not changing anything while Madhusudan was changing the file, |
|
765 incidentally. |
|
766 |
|
767 Now, let's say, both of us are editing the file at the same time, but |
|
768 different parts of it. Say, I change the title of the section 2. |
|
769 :: |
|
770 |
|
771 $ hg diff |
|
772 diff -r 3cd54926dbea chapter1.txt |
|
773 --- a/chapter1.txt Fri Jan 28 23:08:25 2011 +0530 |
|
774 +++ b/chapter1.txt Fri Jan 28 23:45:19 2011 +0530 |
|
775 @@ -10,7 +10,7 @@ |
|
776 Table of Contents |
|
777 ================= |
|
778 1 Introduction and Motivation |
|
779 -2 Creating |
|
780 +2 Creating repositories |
|
781 3 Revision history |
|
782 4 Making and sharing changes |
|
783 5 Getting repositories |
|
784 $ hg commit |
|
785 $ hg push |
|
786 pushing to /home/punchagan/book-repo |
|
787 searching for changes |
|
788 adding changesets |
|
789 adding manifests |
|
790 adding file changes |
|
791 added 1 changesets with 1 changes to 1 files |
|
792 $ |
|
793 |
|
794 Also, let us assume Madhusudan adds an additional section called References. |
|
795 :: |
|
796 |
|
797 $ hg diff |
|
798 diff -r 3cd54926dbea chapter1.txt |
|
799 --- a/chapter1.txt Fri Jan 28 23:08:25 2011 +0530 |
|
800 +++ b/chapter1.txt Fri Jan 28 23:47:05 2011 +0530 |
|
801 @@ -15,4 +15,4 @@ |
|
802 4 Making and sharing changes |
|
803 5 Getting repositories |
|
804 6 Merges and Conflicts |
|
805 - |
|
806 +7 References |
|
807 $ hg commit |
|
808 $ hg log |
|
809 |
|
810 Let us now compare the logs of the two repositories. You can see that both |
|
811 the repositories have their topmost revision numbered as 4, but they are both |
|
812 different. The identification number given to each revision is a local |
|
813 identification. The hexadecimal string following that number is the actual |
|
814 unique identification of that changeset, which will be unique across |
|
815 repositories. |
|
816 |
|
817 What happens now, when Madhusudan tries to push his changes to the central |
|
818 repository? |
|
819 |
|
820 :: |
|
821 |
|
822 $ hg push |
|
823 pushing to http://192.168.1.101:8000 |
|
824 searching for changes |
|
825 abort: push creates new remote heads! |
|
826 (did you forget to merge? use push -f to force) |
|
827 |
|
828 |
|
829 The push failed! This is because, both of us have made changes, and they need |
|
830 to be merged somehow. **Don't**, just for this one instance, take the advice |
|
831 given by ``mercurial``. Using the ``-f`` would be disastrous. We will leave |
|
832 out a discussion of that, for this course. |
|
833 |
|
834 Madhusudan now needs to pull the new changes that have been pushed to the |
|
835 repository after his last pull and **merge** them with his changes. |
|
836 |
|
837 :: |
|
838 |
|
839 $ hg pull |
|
840 pulling from http://192.168.1.101:8000 |
551 searching for changes |
841 searching for changes |
552 adding changesets |
842 adding changesets |
553 adding manifests |
843 adding manifests |
554 adding file changes |
844 adding file changes |
555 added 1 changesets with 1 changes to 1 files (+1 heads) |
845 added 1 changesets with 1 changes to 1 files (+1 heads) |
556 (run 'hg heads' to see heads, 'hg merge' to merge) |
846 (run 'hg heads' to see heads, 'hg merge' to merge) |
557 |
847 $ hg merge |
558 There we go, since both repo were on different track, hg pull command in last line gives some heading from here. *hg heads* command show current repository heads or show branch heads. :: |
848 merging chapter1.txt |
559 |
849 0 files updated, 1 files merged, 0 files removed, 0 files unresolved |
560 $ hg heads |
850 (branch merge, don't forget to commit) |
561 changeset: 4:71fd776d856b |
851 |
|
852 We have now pull the changes from the central repository and merged them with |
|
853 the changes in our repository. But, ``hg`` is warning us not to forget to |
|
854 commit. Let's see what is the status of the repository at this point in time. |
|
855 |
|
856 :: |
|
857 |
|
858 $ hg st |
|
859 M chapter1.txt |
|
860 $ hg diff |
|
861 diff -r bd57162c31f6 chapter1.txt |
|
862 --- a/chapter1.txt Fri Jan 28 23:51:52 2011 +0530 |
|
863 +++ b/chapter1.txt Sat Jan 29 00:00:39 2011 +0530 |
|
864 @@ -10,7 +10,7 @@ |
|
865 Table of Contents |
|
866 ================= |
|
867 1 Introduction and Motivation |
|
868 -2 Creating |
|
869 +2 Creating repositories |
|
870 3 Revision history |
|
871 4 Making and sharing changes |
|
872 5 Getting repositories |
|
873 |
|
874 As you can see, the changes pushed by us, changing the name of the section 2, |
|
875 have now been made in the repository of Madhusudan. We will now need to |
|
876 commit these changes. |
|
877 |
|
878 :: |
|
879 |
|
880 $ hg commit |
|
881 |
|
882 We shall be using a commit message that makes it clear that we are merging. |
|
883 We can now push this changes to the central repository. We could also check |
|
884 the changes that will be pushed, before pushing them, using the ``hg |
|
885 outgoing`` command. |
|
886 :: |
|
887 |
|
888 $ hg outgoing |
562 tag: tip |
889 tag: tip |
563 parent: 2:a5d8cb2fac01 |
890 parent: 5:bd57162c31f6 |
564 user: Vattam <vattam@fossee.in> |
891 parent: 4:5c88c36f60de |
565 date: Wed Feb 24 12:54:31 2010 +0530 |
892 user: Madhusudan CS <madhusudancs@fossee.in> |
566 summary: Added some suggestions. |
893 date: Sat Jan 29 00:02:53 2011 +0530 |
567 |
894 summary: Merge heads. |
568 changeset: 3:02b49a53063f |
895 |
569 user: Shantanu <Shantanu@fossee.in> |
896 changeset: 5:bd57162c31f6 |
570 date: Wed Feb 24 13:12:26 2010 +0530 |
897 parent: 3:3cd54926dbea |
571 summary: Changed name. |
898 user: Madhusudan CS <madhusudancs@fossee.in> |
572 |
899 date: Fri Jan 28 23:51:52 2011 +0530 |
573 To get better understanding of what is going on hg have a tool known as *glog* which shows revision history alongside an ASCII revision graph. :: |
900 summary: Add additional References section |
574 |
901 $ hg push |
575 $ hg glog |
902 pushing to http://192.168.1.101:8000 |
576 |
903 searching for changes |
577 .. image:: heads.png |
904 adding changesets |
578 |
905 adding manifests |
579 To bring repo on single track/branch once again we will have to merge these two branches. Without merging them even hg update wont work for obvious reason of confusing track record. :: |
906 adding file changes |
580 |
907 added 2 changesets with 2 changes to 1 files |
581 $ hg up |
908 |
582 abort: crosses branches (use 'hg merge' or 'hg update -C') |
909 The changes have now been successfully pushed! Let us look at the web |
583 |
910 interface of the repo, to see that the changes have actually taken place. Let |
584 *hg merge* command merge working directory with another revision. :: |
911 us also have a look at the graph to, try and understand what has happened. |
585 |
912 |
|
913 As we can see, a branch was created, when both of us started editing the file |
|
914 simultaneously, and was then merged by Madhusudan CS. |
|
915 |
|
916 Simultaneous Conflicting Changes |
|
917 -------------------------------- |
|
918 |
|
919 We were lucky this time, in that we were editing separate parts of the file. |
|
920 What will happen if we edited the same portion of the file, at the same time? |
|
921 How would merges work? This will be the last thing that we are going to see |
|
922 in this part of the course. |
|
923 |
|
924 Let's say both of us edit the title of the section 6. |
|
925 |
|
926 Let's say, I make the following changes, commit them and push them. |
|
927 |
|
928 :: |
|
929 |
|
930 $ hg diff |
|
931 diff -r ce3469a9446f chapter1.txt |
|
932 --- a/chapter1.txt Sat Jan 29 00:02:53 2011 +0530 |
|
933 +++ b/chapter1.txt Sat Jan 29 10:30:21 2011 +0530 |
|
934 @@ -14,5 +14,5 @@ |
|
935 3 Revision history |
|
936 4 Making and sharing changes |
|
937 5 Getting repositories |
|
938 -6 Merges and Conflicts |
|
939 +6 Merging and resolving conflicts |
|
940 7 References |
|
941 $ hg commit |
|
942 $ hg push |
|
943 ... |
|
944 added 1 changesets with 1 changes to 1 files |
|
945 |
|
946 Meanwhile, let's say Madhusudan was changing the same section title, as |
|
947 follows. |
|
948 |
|
949 :: |
|
950 |
|
951 $ hg diff |
|
952 diff -r ce3469a9446f chapter1.txt |
|
953 --- a/chapter1.txt Sat Jan 29 00:02:53 2011 +0530 |
|
954 +++ b/chapter1.txt Sat Jan 29 10:35:29 2011 +0530 |
|
955 @@ -14,5 +14,5 @@ |
|
956 3 Revision history |
|
957 4 Making and sharing changes |
|
958 5 Getting repositories |
|
959 -6 Merges and Conflicts |
|
960 +6 Simple Merges and Merges with Conflicts |
|
961 7 References |
|
962 $ hg commit |
|
963 $ hg push |
|
964 pushing to http://192.168.1.101:8000 |
|
965 searching for changes |
|
966 abort: push creates new remote heads! |
|
967 (did you forget to merge? use push -f to force) |
|
968 $ hg pull |
|
969 ... |
|
970 added 1 changesets with 1 changes to 1 files (+1 heads) |
|
971 (run 'hg heads' to see heads, 'hg merge' to merge) |
586 $ hg merge |
972 $ hg merge |
587 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
973 0 files updated, 1 files merged, 0 files removed, 0 files unresolved |
588 (branch merge, don't forget to commit) |
974 (branch merge, don't forget to commit) |
589 |
975 |
590 After merging two branches, until we commit the results of merge it will keep on showing two heads. :: |
976 |
591 |
977 What happens now actually depends on how Mercurial is configured and the |
592 $ hg ci -u "Shantanu <shantanu@fossee.in>" -m "Merged branches." |
978 programs available in your machine. You will either get a diff view with 3 |
593 $ hg glog |
979 panes or ``merge`` will insert markers in your file at the points where the |
594 |
980 conflicts occur. |
595 .. image:: glog-2.png |
981 |
596 |
982 If you get a 3 pane view, the first pane is the actual file, where you make |
597 *And we are back on track.* |
983 changes, to resolve the conflicts. The second pane shows the changes that you |
598 |
984 made, to the file. The last pane shows the changes that you pulled from the |
599 Workflow: |
985 original repo. Once you are satisfied with the changes, save and quit. |
600 ========= |
986 |
601 |
987 If you have a very minimal system, you might end up getting a file with |
602 This is chain of steps which can be followed for working against a project that has a centralized copy, you may want to make sure you're up to date first. This means pulling its changes and then updating. |
988 change markers, the original file being backed up. Open the file and resolve |
603 |
989 the conflicts, deleting the markers. Once you are done, you need to tell |
604 For example: :: |
990 mercurial that you have resolved the conflicts manually. |
605 |
991 |
606 $ hg pull |
992 :: |
607 $ hg update |
993 |
608 |
994 $ hg resolve -m chapter1.txt |
609 This will grab the remote changes from the location you first cloned from. Then it will apply the changes. You can do this in one go with: :: |
995 |
610 |
996 Whatever be the process you have used for the merge, you will now need to |
611 $ hg pull -u |
997 commit your changes, just like the simple merge that we performed. |
612 |
998 |
613 Now let's say you make some changes. You edit a file and you want to commit your change. You can do this with: :: |
999 :: |
614 |
1000 |
615 $ hg commit |
1001 $ hg commit -m "Merge heads." |
616 |
|
617 An editor will pop-up asking you to write a message describing your change. When you're done for the day, and you have required changesets sitting in your repository. Before pushing to upstream make sure to pull and update and merge branches if required, once everything looks okay and you have single track, push the changes, :: |
|
618 |
|
619 $ hg push |
1002 $ hg push |
620 |
1003 |
621 Cheatsheet |
1004 *Note*, we have used a different way to commit. We have used the ``-m`` |
|
1005 argument with the commit message. |
|
1006 |
|
1007 We could look at the graph of the changes, in our web interface, being served |
|
1008 by the ``hg serve`` command. From the graph it is clear, how the merging has |
|
1009 occurred. |
|
1010 |
|
1011 That brings us to the end of this tutorial on Mercurial. What we have covered |
|
1012 is nothing close to all the features of Mercurial. We've only scratched the |
|
1013 surface, but let's hope that this will get you started and you will be able |
|
1014 to organize your work and projects, better. |
|
1015 |
|
1016 Additional Reading |
|
1017 ================== |
|
1018 |
|
1019 I strongly suggest you to go through the following topics, if and when you |
|
1020 start using Mercurial on a day-to-day basis. |
|
1021 |
|
1022 1. ``.hgignore`` |
|
1023 #. ``hg rollback`` |
|
1024 #. ``hg bisect`` |
|
1025 #. ``hg backout`` |
|
1026 |
|
1027 |
|
1028 References |
622 ========== |
1029 ========== |
623 |
1030 |
624 .. image:: mod.png |
1031 - `A Visual Guide to Version Control <http://betterexplained.com/articles/a-visual-guide-to-version-control/>`_ |
625 |
1032 - `Version Control for the Masses <http://karlagius.com/2009/01/09/version-control-for-the-masses/>`_ |
626 Suggested Reading: |
1033 - `(Illustrated) Intro to Distributed Version Control <http://betterexplained.com/articles/intro-to-distributed-version-control-illustrated/>`_ |
627 ================== |
1034 - `Understanding Mercurial <http://mercurial.selenic.com/wiki/UnderstandingMercurial>`_ |
628 |
1035 - `A Tutorial on Using Mercurial <http://mercurial.selenic.com/wiki/Tutorial>`_ |
629 * http://karlagius.com/2009/01/09/version-control-for-the-masses/ |
1036 - `Hg Init: a Mercurial tutorial <http://hginit.com/>`_ |
630 * http://betterexplained.com/articles/a-visual-guide-to-version-control/ |
1037 - `Beginners Guides <http://mercurial.selenic.com/wiki/BeginnersGuides>`_ |
631 * http://en.wikipedia.org/wiki/Revision_control |
1038 - `Software Carpentry <http://software-carpentry.org/4_0/vc/>`_ |
632 * http://hgbook.red-bean.com/ |
1039 |
633 * http://betterexplained.com/articles/intro-to-distributed-version-control-illustrated/ |
1040 |
634 * http://wiki.alliedmods.net/Mercurial_Tutorial |
1041 Appendix A - Definitions |
|
1042 ======================== |
|
1043 |
|
1044 Definitions of a few commonly used terms. |
|
1045 |
|
1046 Add |
|
1047 Begin tracking a file (or a set of files) with Version Control. |
|
1048 |
|
1049 Branch |
|
1050 A diverged line of development. |
|
1051 |
|
1052 Changeset |
|
1053 An atomic collection of changes to the files in a repository. |
|
1054 |
|
1055 Clone |
|
1056 Creating a copy of an existing repository; New repo is self-contained. |
|
1057 |
|
1058 Commit |
|
1059 Taking a snapshot of the changes made in the repository (after the |
|
1060 previous snapshot) |
|
1061 |
|
1062 Conflict |
|
1063 Occurs when two changesets have overlapping sections that have been |
|
1064 modified. |
|
1065 |
|
1066 Head |
|
1067 A changeset with no child changesets. |
|
1068 |
|
1069 History |
|
1070 Cumulative of all the changesets of a repository. |
|
1071 |
|
1072 Merge |
|
1073 Combining two separate changesets into one merge changeset. |
|
1074 |
|
1075 Repository (repo) |
|
1076 - Loosely speaking, the folder with all the files and a store |
|
1077 of the change history. |
|
1078 - Strictly speaking, only the ``.hg`` directory that contains the change |
|
1079 history. |
|
1080 |
|
1081 Revert |
|
1082 Going back to previous committed state of working directory or a file. |
|
1083 |
|
1084 Revision |
|
1085 A particular changeset. |
|
1086 |
|
1087 Server |
|
1088 A machine which serves the repository. |
|
1089 |
|
1090 Tip |
|
1091 Most recently changed head in a repository. |
|
1092 |
|
1093 Update |
|
1094 Updating the working directory to a particular revision or to the tip |
|
1095 revision. |
|
1096 |
|
1097 Working Directory |
|
1098 The directory where all of the files and directories of the project are |
|
1099 present. |
|
1100 |
|
1101 .. |
|
1102 Local Variables: |
|
1103 mode: rst |
|
1104 indent-tabs-mode: nil |
|
1105 sentence-end-double-space: nil |
|
1106 fill-column: 77 |
|
1107 End: |
|
1108 |