Last modified: Nov 20, 2013
Distributed version controls models relax the dependency upon a central repository as the keeper of the one true project.
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
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
Suppose each repository adds a commit along the trunk:
Fetching Remote Changes
The basic command to get changes from the remote repository is git~fetch %\saveAndMeasurePic[0.55\linewidth]{gitFetched}
If states are not identical, they are fetched as new branches
Local heads are unaffected
Pulling Remote Changes
git pull origin master
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
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.
Eclipse Integration
Again, a plugin (Egit) is needed. Egit has recently been incorporated into the Eclipse main update/plugin distribution site.
Operations is similar to the CVS and SVN plugins, except that
The Team menu gains new commands to push and pull.
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.
For non-Java projects, 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.