Last modified: Mar 23, 2015
Abstract
Distributed version controls models relax the dependency upon a central repository as the keeper of the one true project.
We will look at git, a popular distributed version control system.
Sounds Like Anarchy
In practice, projects often due have a central repository for “official” releases.
A Synthesis of Local and Remote
In a distributed model, a developer maintains
Two-Level Commits
The local/remote division helps resolve a common dilemma in centralized VC systems:
A newly checked-out copy should always compile and yield a (roughly) working product.
a.k.a., “Don’t break the build!”
git Revisions
Revision numbers are therefore replaced by hash codes computed over the file set that constitutes the entire project
git Revisions
A git repository contains, conceptually, a collection of snapshots (a.k.a., commit objects, a.k.a. revisions, a.k.a. versions).
Each snapshot contains
The set of files for the project
The name of this snapshot (hash code)
Heads
A git repository also contains a collection of heads.
These are human-assigned names for selected snapshots.
Every repository has a head “master”.
At any given time, one head is considered active. This one is aliased to the head “HEAD”.
How shall I name thee?
Snapshots in a repository may be identified by giving
Its SHA1 hashcode
A long enough prefix of that hashcode to be unique
By a head
Common Local History Commands
git status lists modified files
git diff file displays what was changed
Every Local Repository is a Branch
So one way to “branch” in git is to simply check out a new copy.
But sometimes we want to branch within a local repository
Branching Within a Local Repository
git branch newHeadName/*-i desiredParentSnapshot
creates a new branch
git checkout branchHead
switches to a new branch
When Should I Commit? (Another perspective)
git users consider branches to be cheap.
So some advocate
Always work in branches
Keep the master branch in a releasable state
Merging Local Branches
git merge head
produces a new snapshot representing the merge of the current one (HEAD) with the named head.
The merged revision will have both HEAD and head as parents.
Branches not needed after a merge can be deleted
git branch -d head removes the head name from the repository (but does not actually delete the history of changes along the branch.
Collaboration in git takes the form of interaction between your local repository and a remote repository.
Starting from a Remote Repository
If you are working with an existing remote repository
git clone remoteSpec
creates a new local repository as a copy of the remote one.
Cloning
Suppose that we have a remote repository with two branches and a few commit objects on each.
Our local cloned repository will remember its remote origin repository.
All heads from the remote repository will be cloned as origin/head
We will get a local master head
You can request local heads for non-master branches by tracking, e.g.
git branch --track enhanced origin/enhanced
Life after Cloning
Starting from this local repository, …
… suppose each repository adds a commit along the trunk:
Our local heads separate from the remembered positions of the remote ones.
Fetching Remote Changes
The basic command to get changes from the remote repository is git fetch
Remember, each repository is, in essence, a new (set of) branch(es)
If states are not identical, they are fetched as new branches
Local heads are unaffected
Pulling Remote Changes
More commonly used than fetching is pulling, which combines a fetch and a merge
Starting with this remote repository…
…and this local one.
(Note that commits (F, G) have been made to both repositories since the clone was created.)
Then
git pull origin master
yields this new version of the local:
Pushing to the Remote Repository
The push command
sends local commits to a remote repository
Advances the remote head marker to the end of the list of changes.
git push origin master
yields this remote repository.
Push is NOT the Opposite of Pull
It’s actually the opposite of fetch
This leads to an important restriction
The remote head must point, before a push, to an ancestor of the commit that it would point to after the push.
This Push Will Fail
because if it went through, we would lose access to a state already committed in the remote repository.
Avoiding Bad Pushes
An alternative is rebasing
Rebasing
Rebasing changes the parent relationship of the current head so that it appears to have been derived directly from some other selected head.
git rebase master
The Perils of Rebasing
For all the talk about rebasing in the git literature, you would think it was a very common operation.
But,
done at the wrong time, can make pushing to a remote server much harder
Why Rebase?
Generally recommended only for
Managing an unshared branch that you want to keep up to date with the master and don’t care if you lose history.
You fetch their changes
Then rebase your head to appear as if it were derived from their head.
You can then push, because you have guaranteed that the remote head is an ancestor of yours
Unless someone else sneaks in yet another push while you are doing the rebase.
Isn’t distributed access fun?!
The (Egit) plugin integrates git into Eclipse.
Operations is similar to the CVS and SVN plugins, except that
The Team menu gains new commands to push and pull.
A typical work session using egit
Eclipse, git, and a Forge
New projects:
A Forge environment will create an empty repository
In Eclipse, do File ⇒ Import and select Git. Follow the instructions to name your local repository that you just cloned and “Use New Project Wizard”.
When the regular project wizard starts, direct it to your project folder you created in step 3.
Use Team ⇒ Add to index to add files to version control.
Team ⇒ Commit (or Synchronize).
Team ⇒ Push.
Existing Projects
A Forge environment will contain instructions/settings on how to access the existing repository
Create a new Java project, outside of the default workspace location. For the location, navigate to your newly created copy of the project directory, within the directory where you cloned the git repository.
Or, for non-Java projects, File ⇒Import and select
Git. Follow the instructions to name your local repository that
you just cloned and use the New Project Wizard .
When the regular project wizard starts, direct it to your project folder you created in step 3.
Use Team ⇒ Add to index to add files to version control.
Team ⇒ Commit (or Synchronize).
Team ⇒ Push.
from The System