Skip to content

Instantly share code, notes, and snippets.

@jhidalgo3
Created June 17, 2014 08:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jhidalgo3/248ab29b92ae00a52b82 to your computer and use it in GitHub Desktop.
Save jhidalgo3/248ab29b92ae00a52b82 to your computer and use it in GitHub Desktop.

Git vs. CVS Advantages

Flexible Workflow

In Git your working copy is a clone of the entire repository. This includes branches and tags. This decreases the overhead (speed and manual work) involved when switching contexts and the need to be connected to a network. Some examples are:

  • When switching branches there is no need to connect to a remote server or close your IDE/project and open a checkout in another directory. Running git checkout [branch name] is all you need to do.
  • When merging you do not need a connection to the remote server, you have all branches locally. Since branches are so cheap in Git you could create a new branch to perform the merge in so that if you had a large amount of conflicts you could incrementally work on and commit without affecting the main branch then merge or create a patch after everything has been fixed.
  • Because Git is a distributed system in addition to connecting to a central repository developers can connect to another developers repository. This allows teams to share code without affecting the central repository.

Many of Git's features are designed around improving or being able to deal with the development workflow. Some interesting features are:

  • git stash -- Can be used when you are in the middle of coding something and are not at a point you feel comfortable committing then interrupted to work on something with immediate priority. This will create a special type of tag (without commit) that has to be unstashed and will not get pushed or pulled.
  • git checkout -b [new branch] [source branch] -- Branching is central enough in Git that it's checkout command allows you to create a new branch during the checkout process.

Tracking

In most systems tracking is done on files and versioned at either the file or commit. Git however tracks content (which is what is really important anyways). Because of this Git is capable of tracking things like a method being moved from one class to another class and being able to include the history prior to the move.

Command Reference

TaskCVSGitNote
Checkout a branch cvs checkout -r [branch] [module] git checkout [branch] With git you will need to have already cloned the repository. git clone [repository]
Add files cvs add [file] git add [file] Git has a stage area, git add will places the files in this area.
Commit changes cvs ci git commit With Git you can automatically stage and commit modifications and deletes using git commit -a (new files still need to be added or staged).
Since git commit only affects the local repository if you need to commit to a remote repository you would need to use git push or git push [repository] [branch] or from the other repository pull the changes git pull [repository] [branch]
Update cvs up git pull With Git you can pull from any branch in any repository using git pull [repository] [branch]
Merge cvs up -j [branch] -j [branch] git fetch or git merge or git pull or git push

From Git Magic

Let’s suppose the previous problem is ten times worse. After a lengthy session you’ve made a bunch of commits. But you’re not quite happy with the way they’re organized, and some of those commit messages could use rewording. Then type:

$ git rebase -i HEAD~10

and the last 10 commits will appear in your favourite $EDITOR. A sample excerpt:

pick 5c6eb73 Added repo.or.cz link
pick a311a64 Reordered analogies in "Work How You Want"
pick 100834f Added push target to Makefile

Then:

  • Remove commits by deleting lines.
  • Reorder commits by reordering lines.
  • Replace pick with:
    • edit to mark a commit for amending.
    • reword to change the log message.
    • squash to merge a commit with the previous one.
    • fixup to merge a commit with the previous one and discard the log message.
  • Save and quit. If you marked a commit for editing,

Then run:

$ git commit --amend

Otherwise, run:

$ git rebase --continue

So commit early and commit often: you can tidy up later with rebase.

Important Differences from CVS

  • HEAD -- In Git this is a reserved branch name and points to the currently active branch. A branch called master is Git's equivalent to cvs's HEAD
  • fast forward -- By default when doing merge operations (pull,push,merge) if there are no conflicts git will automatically commit.

Technical Stuff

Repository Structure

Objects

  • blobs -- Usually files but could be almost anything.
  • trees -- Used to store information about directories, trees for sub-directories, and blobs for files within directories.
  • commits -- A snapshot of a tree at the time of a commit. Also references zero or more parent commits
  • refs -- Refer to heads and branches.
  • remote refs -- refs given their own namespace and controlled by a remote repository.
  • tag -- Pointer to a commit

Each of these objects are identified by an Object Name which is an SHA1 hash of the object's state (not just content).

Using Git with CVS

Workflow

Setup

With the following setup it would be ideal to have the CVS checkouts and Git gateway pieces at a central location rather than maintained on each developer's workstation in order to take better advantage of Git's capabilities. Commits into CVS would be less frequent and more controlled with less chance of build breaking.

CVS Checkouts

  1. Checkout CVS HEAD
  2. Checkout another branch_x from CVS
  3. Create a Git repository on top of the CVS HEAD and one on top of the branch_x checkout.

Commands mkdir /repo mkdir /repo/cvs cd /repo/cvs cvs co [module] head cvs co -r branch_x branch_x cd head git init git add . git commit cd ../branch_x git init git add . git commit

Gateway

  1. Create an empty Git repository to use as a gateway.
  2. Create a branch called cvshead for CVS HEAD and a branch called branch_x for branch_x.
  3. Add remotes for both CVS checkouts.
  4. Get information from remotes
  5. Checkout the cvshead branch.
  6. Pull CVS HEAD into the branch.
  7. Checkout the branch_x branch
  8. Pull CVS branch_x into the branch.

Commands cd /repo mkdir gateway cd gateway git init git remote add cvs.head ../cvs/head git remote add cvs.branch_x ../cvs/branch_x git remote update git checkout -b cvshead cvs.head/master git checkout -b branch_x cvs.branch_x/master

Working copy

  1. Clone the gateway repository

Commands git clone /repo/gateway ~/wc

You can now use your working copy clone of the gateway (and to a certain extent the gateway) as a normal Git repository creating branches pulling and pushing changes as needed.

Committing back to CVS (HEAD)

  1. Push changes to the gateway from your clone. (you could also pull changes into the gateway)
  2. Push changes in the gateway to the remote (cvs checkout) for HEAD
  3. Commit changes to CVS

Commands cd ~/wc git push cd /repo/gateway git checkout cvshead git push cvs.head/master cvshead cd /repo/cvs/head cvs ci

or

cd /repo/gateway
git checkout cvshead
git pull ~/wc wc_branch_name
cd /repo/cvs/head
git pull /repo/gateway cvshead
cvs ci
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment