Version Control System (VCS)

What?

Version control systems (VCS) most commonly run as stand-alone applications, but revision control is also embedded in various types of software such as word processors and spreadsheets, e.g., Google Docs and Sheets and in various content management systems, e.g., Wikipedia's Page history.

Revision control allows for the ability to revert a document to a previous revision, which is critical for allowing editors to track each other's edits, correct mistakes, and defend against vandalism and spam. Wikipedia

Why?

A version control system (VCS) is a tool for managing a collection of program code that provides you with three important capabilities:

  • reversibility,
  • concurrency,
  • and annotation.

The first VCSes were built as support technology for computer programmers, and that is still their primary use, but they can be used for Web content or any other sort of document or data file stored on a computer. See for example GeoGit is a project to share and track all the changes in a geospatial data set.

The most basic capability you get from a VCS is reversibility, the ability to back up to a saved, known-good state when you discover that some modification you did was a mistake or a bad idea.

VCSes also support concurrency, the ability to have many people modifying the same collection of code or documents knowing that conflicting modifications can be detected and resolved.

Finally, VCSes give you the capability to annotate your data, attaching explanatory comments about the intention behind each change to it and a record of who was responsible for each change. Even for a programmer working solo, change histories are an important aid to memory; for a multi-person project they become a vitally important form of communication among developers. Read more here.

Which one should you use?

There are a lot of different VCS, but two main VCS are growing faster than other and have a huge community of developers and users and are:

So why I'm going to present Hg, because is written in python, and these things matter in a python course! ;-)

Secondly mercurial/Tortoisehg are already present in the Winpython package, so you don't have to install another software.

Last but not least both the systems have very strong similiraties to each other, so if you know how to use one is quite easy to use the other one.

Prepare Mercurial

Before to start I have to say that everything is shown here is doable also using a Graphic User Interface (GUI) like: tortoisehg, and you can find a tutorial that explain how: here.

But I want to write each step to assure the reproducibility and focus on the workflow.

As first step, you should teach Mercurial your name. For that you open the file ~/.hgrc (or %USERPROFILE%\Mercurial.ini or %HOME%\Mercurial.ini in Windows ) with a text-editor and add the ui section (user interaction) with your username

[ui] username = Mr. Johnson [extensions] color = shelve =

Initialize the project

First step create a directory.

In [1]:
%%sh
mkdir testhg

Now eneter into the new directory

In [2]:
%cd testhg
/home/pietro/docdat/phd/pubblicazioni/eurac/corso/testhg

Now we can start to take track of our project, just type:

In [3]:
%%sh
hg init

Check the status

In [4]:
%%sh
hg status

Add a new file, like: README and check the status.

In [5]:
%%file README
Start a new amazing project                                                 
=============================
Writing README
In [6]:
%%sh 
hg status
? README

Add files and track them

Enter the project folder, create some files, then add and commit them.

In [7]:
%%sh
hg add README
In [8]:
%%sh
hg status
A README

see the exact changes

In [9]:
%%sh
hg diff README
diff -r 000000000000 README
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README	Fri Feb 14 17:22:05 2014 +0000
@@ -0,0 +1,2 @@
+Start a new amazing project                                                 
+=============================

Record the change

In [10]:
%%sh
hg commit -m "Start to use Hg"

See the changes

In [11]:
%%sh
hg status
In [12]:
%%sh
hg log
changeset:   0:e391cff30cc7
tag:         tip
user:        Pietro Zambelli <[email protected]>
date:        Fri Feb 14 17:22:14 2014 +0000
summary:     Start to use Hg

Now modify the README file.

In [14]:
%%file README
Start a new amazing project                                                 
=============================

How to install
---------------

Bla bla
Overwriting README
In [15]:
%%sh 
hg status
M README
In [16]:
%%sh
hg diff README
diff -r e391cff30cc7 README
--- a/README	Fri Feb 14 17:22:14 2014 +0000
+++ b/README	Fri Feb 14 17:22:54 2014 +0000
@@ -1,2 +1,7 @@
 Start a new amazing project                                                 
 =============================
+
+How to install
+---------------
+
+Bla bla
In [17]:
%%sh
hg commit -m "Add the section: 'how to install'."
In [18]:
%%sh
hg log
changeset:   1:82d53c0a8b30
tag:         tip
user:        Pietro Zambelli <[email protected]>
date:        Fri Feb 14 17:23:09 2014 +0000
summary:     Add the section: 'how to install'.

changeset:   0:e391cff30cc7
user:        Pietro Zambelli <[email protected]>
date:        Fri Feb 14 17:22:14 2014 +0000
summary:     Start to use Hg

In [19]:
%%sh
hg log --style compact
1[tip]   82d53c0a8b30   2014-02-14 17:23 +0000   peter
  Add the section: 'how to install'.

0   e391cff30cc7   2014-02-14 17:22 +0000   peter
  Start to use Hg

In [20]:
%%sh
hg log --style changelog
2014-02-14  Pietro Zambelli  <[email protected]>

	* README:
	Add the section: 'how to install'.
	[82d53c0a8b30] [tip]

	* README:
	Start to use Hg
	[e391cff30cc7]

Working with branches

See which branch are active

In [21]:
%%sh
hg branches
default                        1:82d53c0a8b30

Create a new branch

In [22]:
%%sh
hg branch newidea
marked working directory as branch newidea
(branches are permanent and global, did you want a bookmark?)
In [23]:
%%sh
hg branch
newidea

Modify the REDME file

In [25]:
%%file README
Start a new amazing project                                                 
=============================

How to install
---------------

Bla bla


Add new ideas
--------------

This and that
Overwriting README
In [26]:
%%sh
hg status
M README
In [27]:
%%sh
hg diff
diff -r 82d53c0a8b30 README
--- a/README	Fri Feb 14 17:23:09 2014 +0000
+++ b/README	Fri Feb 14 17:24:41 2014 +0000
@@ -5,3 +5,9 @@
 ---------------
 
 Bla bla
+
+
+Add new ideas
+--------------
+
+This and that
\ No newline at end of file

Now commit the changes

In [28]:
%%sh
hg commit -m "Add the description of the features."

Back to the default branch

In [29]:
%%sh
hg update default
1 files updated, 0 files merged, 0 files removed, 0 files unresolved

As you can see the last change is not present in the README file. We can merge the change from the branch "newidea" => "default" using: hg merge.

In [30]:
%%sh
hg merge newidea
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)

Help

There are a lot of more command that could be useful to work with shared text/code.

In [31]:
%%sh
hg help
Mercurial Distributed SCM

list of commands:

 add           add the specified files on the next commit
 addremove     add all new files, delete all missing files
 annotate      show changeset information by line for each file
 archive       create an unversioned archive of a repository revision
 backout       reverse effect of earlier changeset
 bisect        subdivision search of changesets
 bookmarks     track a line of development with movable markers
 branch        set or show the current branch name
 branches      list repository named branches
 bundle        create a changegroup file
 cat           output the current or given revision of files
 clone         make a copy of an existing repository
 commit        commit the specified files or all outstanding changes
 copy          mark files as copied for the next commit
 diff          diff repository (or selected files)
 export        dump the header and diffs for one or more changesets
 forget        forget the specified files on the next commit
 graft         copy changes from other branches onto the current branch
 grep          search for a pattern in specified files and revisions
 heads         show branch heads
 help          show help for a given topic or a help overview
 identify      identify the working copy or specified revision
 import        import an ordered set of patches
 incoming      show new changesets found in source
 init          create a new repository in the given directory
 locate        locate files matching specific patterns
 log           show revision history of entire repository or files
 manifest      output the current or given revision of the project manifest
 merge         merge working directory with another revision
 outgoing      show changesets not found in the destination
 parents       show the parents of the working directory or revision
 paths         show aliases for remote repositories
 phase         set or show the current phase name
 pull          pull changes from the specified source
 push          push changes to the specified destination
 recover       roll back an interrupted transaction
 remove        remove the specified files on the next commit
 rename        rename files; equivalent of copy + remove
 resolve       redo merges or set/view the merge status of files
 revert        restore files to their checkout state
 root          print the root (top) of the current working directory
 serve         start stand-alone webserver
 showconfig    show combined config settings from all hgrc files
 status        show changed files in the working directory
 summary       summarize working directory state
 tag           add one or more tags for the current or given revision
 tags          list repository tags
 unbundle      apply one or more changegroup files
 update        update working directory (or switch revisions)
 verify        verify the integrity of the repository
 version       output version and copyright information

enabled extensions:

 color         colorize output from some commands

additional help topics:

 config        Configuration Files
 dates         Date Formats
 diffs         Diff Formats
 environment   Environment Variables
 extensions    Using Additional Features
 filesets      Specifying File Sets
 glossary      Glossary
 hgignore      Syntax for Mercurial Ignore Files
 hgweb         Configuring hgweb
 merge-tools   Merge Tools
 multirevs     Specifying Multiple Revisions
 patterns      File Name Patterns
 phases        Working with Phases
 revisions     Specifying Single Revisions
 revsets       Specifying Revision Sets
 subrepos      Subrepositories
 templating    Template Usage
 urls          URL Paths

use "hg -v help" to show builtin aliases and global options

As you see the most used are:

  • hg init => to start a new repo
  • hg clone => to clone an existing repo
  • hg add => to add new files
  • hg status => to check the status of the repository
  • hg diff => to see the changes
  • hg commit => to record the changes
  • hg pull => to pull the update from the repo
  • hg push => to publish your changes to the repo
  • hg rename => to rename/move files and directories
  • hg remove => to remove files and directories
  • hg merge => to solve conflict

For each of them you can have more details with:

hg help <command>

for example:

In [10]:
%%sh
hg help rename
hg rename [OPTION]... SOURCE... DEST

aliases: move, mv

rename files; equivalent of copy + remove

    Mark dest as copies of sources; mark sources for deletion. If dest is a
    directory, copies are put in that directory. If dest is a file, there can
    only be one source.

    By default, this command copies the contents of files as they exist in
    the working directory. If invoked with -A/--after, the operation is
    recorded, but no copying is performed.

    This command takes effect at the next commit. To undo a rename before
    that, see "hg revert".

    Returns 0 on success, 1 if errors are encountered.

options:

 -A --after               record a rename that has already occurred
 -f --force               forcibly copy over an existing managed file
 -I --include PATTERN [+] include names matching the given patterns
 -X --exclude PATTERN [+] exclude names matching the given patterns
 -n --dry-run             do not perform actions, just print output

[+] marked option can be specified multiple times

use "hg -v help rename" to show the global options

How to share

We can share the repository with other users activating the server, with:

In [ ]:
%%sh
hg serve

See you current IP and share your repository.

In [2]:
import socket
socket.gethostbyname(socket.gethostname())
Out[2]:
'192.168.0.3'
In [ ]:
%%sh
hg branch testremote  # create a new branch
hg pull -f http://192.168.0.3:8000/
# see more info: http://mercurial.selenic.com/wiki/MergingUnrelatedRepositories

Or using a public server