Difference between revisions of "ROMS git"

From WikiROMS
Jump to navigationJump to search
Line 30: Line 30:


===Setup===
===Setup===
<div class="box">git config --global user.name “me”<br />git config --global user.email “me@work”<br />git config --global color.ui “auto”</div>
<div class="box">% git config --global user.name “me”<br />% git config --global user.email “me@work”<br />% git config --global color.ui “auto”</div>
For the first two, substitute "me" with your real name in quotes and "me@work" with your real email address. The third is entirely optional, but provides more colorful output from git. For all, leave out the "--global" argument to have it apply to the current directory only. As it is, it will put information into a .gitconfig file in your home directory.
For the first two, substitute "me" with your real name in quotes and "me@work" with your real email address. The third is entirely optional, but provides more colorful output from git. For all, leave out the "--global" argument to have it apply to the current directory only. As it is, it will put information into a .gitconfig file in your home directory.


===Downloading ROMS===
===Downloading ROMS===
We want to download a specific revision of ROMS rather than the entire history. As I write this, the current revision (visible at [https://www.myroms.org/svn/src/]) is 529. A recent prior version is 526, from just after the annual changing of the Copyright notice in all files. I'd like to fetch something just before the current version so you can see the update and merge procedures. Grabbing rev 526:
We want to download a specific revision of ROMS rather than the entire history. As I write this, the current revision (visible at [https://www.myroms.org/svn/src/]) is 529. A recent prior version is 526, from just after the annual changing of the Copyright notice in all files. I'd like to fetch something just before the current version so you can see the update and merge procedures. Grabbing rev 526:
<div class="box">git svn clone –r 526 --username name https://www.myroms.org/svn/src/trunk [MyDir]</div>Here, "--username name" is not needed if your ROMS userid is the same as your userid on the local computer, "name" being your ROMS name. If you leave off the MyDir argument, it will create a directory called "trunk".
<div class="box">% git svn clone –r 526 --username name https://www.myroms.org/svn/src/trunk [MyDir]</div>Here, "--username name" is not needed if your ROMS userid is the same as your userid on the local computer, "name" being your ROMS name. If you leave off the MyDir argument, it will create a directory called "trunk".


Now you can change into the directory called MyDir or trunk and see all the ROMS directories. There will also be a hidden directory called ".git". One file there that's useful to look at is .git/config, containing information about other repositories it knows about. Since we haven't told it about other remote sites yet, it should look something like:
Now you can change into the directory called MyDir or trunk and see all the ROMS directories. There will also be a hidden directory called ".git". One file there that's useful to look at is .git/config, containing information about other repositories it knows about. Since we haven't told it about other remote sites yet, it should look something like:
Line 42: Line 42:
===Ignoring Files===
===Ignoring Files===
Let's create a ".gitignore" file:
Let's create a ".gitignore" file:
<div class="box">e% cat > .gitignore<br />Build<br />ocean?<br />core*</div>
<div class="box">% cat > .gitignore<br />Build<br />ocean?<br />core*</div>
We can add this to the list of files to be tracked by git:
We can add this to the list of files to be tracked by git:
<div class="box">% git add .gitignore<br />% git commit -m "adding .gitignore"</div>
<div class="box">% git add .gitignore<br />% git commit -m "adding .gitignore"</div>
Line 66: Line 66:


===Fetching Updates===
===Fetching Updates===
Remember that we hadn't grabbed the absolute latest, greatest ROMS? We want to go back to the master branch to bring it in, but first, it's always good practice to make sure there are no stray files lying around:
Remember that we hadn't grabbed the absolute latest, greatest ROMS. We want to go back to the master branch to bring it in, but first, it's always good practice to make sure there are no stray files lying around:
<div class="box">% git status<br /># On branch circle<br />nothing to commit (working directory clean)</div>
<div class="box">% git status<br /># On branch circle<br />nothing to commit (working directory clean)</div>
Now we can go back to the master branch and fetch the updates:
Now we can go back to the master branch and fetch the updates:
<div class="box">% git checkout master<br />% git svn rebase</div>
<div class="box">% git checkout master<br />% git svn rebase</div>
A rebase is a reordering of the commits, in this case putting our changes after the history that's coming from the svn repository:
A rebase is a reordering of the commits, in this case putting our changes after the history that's coming from the svn repository:
<div class="box">First, rewinding head to replay your work on top of it...<br />Applying: adding .gitignore</div> In this case, I want to keep the master branch to be pretty much the same as the ROMS trunk code.
<div class="box">First, rewinding head to replay your work on top of it...<br />Applying: adding .gitignore</div> In this case, I want to keep the master branch as a clean copy of the ROMS trunk code (except for that .gitignore).


===Merging and a Conflict===
===Merging and a Conflict===
Line 78: Line 78:
<div class="box">% git merge master</div> or I can show you a little conflict just for fun. Let's change ROMS/Version to look like:
<div class="box">% git merge master</div> or I can show you a little conflict just for fun. Let's change ROMS/Version to look like:
<div class="box">ROMS/TOMS Framework:  January 19, 2011<br />===================<br /><br />Copyright (c) 2002-2011 The ROMS/TOMS Group<br />  Licensed under a MIT/X style license<br />  See License_ROMS.txt<br /><br />svn: $HeadURL$<br />svn: $LastChangedBy$<br />svn: $LastChangedRevision$<br />svn: $LastChangedDate$<br />svn: $Id$</div>
<div class="box">ROMS/TOMS Framework:  January 19, 2011<br />===================<br /><br />Copyright (c) 2002-2011 The ROMS/TOMS Group<br />  Licensed under a MIT/X style license<br />  See License_ROMS.txt<br /><br />svn: $HeadURL$<br />svn: $LastChangedBy$<br />svn: $LastChangedRevision$<br />svn: $LastChangedDate$<br />svn: $Id$</div>
Notice that the svn stuff like "$HeadURL$" has not been expanded. Some of these tags are read by ROMS, so we can fill in useful there, for at least the URL and author:
Notice that the svn stuff like "$HeadURL$" has not been expanded. Some of these tags are read by ROMS, so we can fill in useful information there, for at least the URL and author:
<div class="box">svn: $https://www.myroms.org/svn/src/trunk/$<br />svn: $arango$</div> Heck if I'm going to keep the revision number up to date, but go for it if you're so inclined.
<div class="box">svn: $https://www.myroms.org/svn/src/trunk/$<br />svn: $arango$</div> Heck if I'm going to keep the revision number up to date, but go for it if you're so inclined.


Line 106: Line 106:
===Last Tips===
===Last Tips===
*Remember to check that "git status" is clean before changing branches.
*Remember to check that "git status" is clean before changing branches.
*Though a git archive can know about multiple other git repositories, it can only know about one svn site and it has to be set up during the "git clone" operation.
*Though a git archive can know about multiple other git repositories, it can only know about one svn site and it has to be set up during the "git svn clone" operation.
* Side by side directories can each point to different svn sites and be a "git remote" of the other (as discussed here [https://www.myroms.org/blog/?p=171]).
* Side by side directories can each point to different svn sites and be a "git remote" of the other (as discussed here [https://www.myroms.org/blog/?p=171]).

Revision as of 19:24, 19 January 2011

Tutorial: Installing ROMS via git

I would like to explain how and why one would install ROMS via git-svn.

What is git?

Git is a distributed version control system available from [1]. That site also contains links to documentation and other resources - even videos! As a distributed system, any copy you make of a repository is complete unto itself, with history and possibly branches. If you download ROMS via git-svn, you now have an environment in which you can save your own changes, create new branches, and keep a history of what you have tried.

As a ROMS developer, I have write access to a branch at the Rutgers svn server, but that's not true of most users. As ROMS users, you still have opportunity to create and modify ROMS files that you might want to manage with some sort of versioning software. This is not easy with svn, in which each "sandbox" can only point to one repository. You've got to have one pointing to the myroms.org site in order to get updates. Then the easiest (but unsatisfactory) way to back up your changes is via tarball.

Prerequisites

You will need:

  • svn
  • git
  • some Perl scripts which come with svn, but aren't always installed
  • Perl

If everything is there and you are in a git sandbox, you can have this sort of exchange:

% git svn --version
git-svn version 1.7.1 (svn 1.6.5)

If everything is there and you are not in a git sandbox, you get this instead:

% git svn --version
fatal: Not a git repository (or any of the parent directories): .git
Already at toplevel, but .git not found
at /Users/kate/libexec/git-core/git-svn line 276

If the Perl scripts are not there, you get something more like:

% git svn --version
Can't locate SVN/Core.pm in @INC (@INC contains: /u1/uaf/kate/...

You might have the best luck with package managers rather than installing from source code.

Procedure

For the Hong Kong training, Dale asked me to set up the CIRCLE test problem, in three different flavors. I did so, but the initial conditions require the use of a C language Bessel function, changing the link rules for ROMS. This is the perfect example of why you would want to be able to create alternate branches. What I am going to lead you through here is setting up three branches:

  • master, a copy of the myroms.org trunk
  • circle, a branch with the special features of the CIRCLE problem
  • my_stuff (or whatever name you like), a place to put your own changes

Setup

% git config --global user.name “me”
% git config --global user.email “me@work”
% git config --global color.ui “auto”

For the first two, substitute "me" with your real name in quotes and "me@work" with your real email address. The third is entirely optional, but provides more colorful output from git. For all, leave out the "--global" argument to have it apply to the current directory only. As it is, it will put information into a .gitconfig file in your home directory.

Downloading ROMS

We want to download a specific revision of ROMS rather than the entire history. As I write this, the current revision (visible at [2]) is 529. A recent prior version is 526, from just after the annual changing of the Copyright notice in all files. I'd like to fetch something just before the current version so you can see the update and merge procedures. Grabbing rev 526:

% git svn clone –r 526 --username name https://www.myroms.org/svn/src/trunk [MyDir]

Here, "--username name" is not needed if your ROMS userid is the same as your userid on the local computer, "name" being your ROMS name. If you leave off the MyDir argument, it will create a directory called "trunk".

Now you can change into the directory called MyDir or trunk and see all the ROMS directories. There will also be a hidden directory called ".git". One file there that's useful to look at is .git/config, containing information about other repositories it knows about. Since we haven't told it about other remote sites yet, it should look something like:

[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
[svn-remote "svn"]
url = https://www.myroms.org/svn/src/trunk
fetch = :refs/remotes/git-svn

Ignoring Files

Let's create a ".gitignore" file:

% cat > .gitignore
Build
ocean?
core*

We can add this to the list of files to be tracked by git:

% git add .gitignore
% git commit -m "adding .gitignore"

Without the "-m string" option, it will open up a text editor, waiting for a description for this commit.

Creating Branches

As we said above, we would like to have three branches at the end, one containing some code for a CIRCLE test problem. Let's start off with that:

% git branch circle
% git checkout circle
% git branch

This last command should just show that we are now in the circle branch:

* circle
master

Now to fetch the circle code from [3]. From the trunk directory, we can apply these changes to the circle branch:

% gunzip Circle.diffs.gz
% patch -p1 < Circle.diffs

We can see what we have with "git status":

% git status
# On branch circle
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: Master/Module.mk
# modified: ROMS/Modules/mod_scalars.F
# modified: ROMS/Utility/checkdefs.F
# modified: ROMS/Utility/def_info.F
# modified: ROMS/Utility/wrt_info.F
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# Apps/
# makefile.circle
no changes added to commit (use "git add" and/or "git commit -a")

A "git commit -a" will add the updates to all the files that git is already tracking. For this case, we want it to track a couple of new things:

% git add Apps makefile.circle

Now we can commit the whole works:

% git commit -a -m "Circle problem"

When in this branch, one can run any of the three Circle cases:

  • CIRLCE_BOX - a square grid with masking
  • CIRCLE_ROUND - requires an external circular grid
  • CIRCLE_POLAR - a donut-shaped domain

If you use build.bash, edit the line near the bottom invoking "make" and change it to "make -f makefile.circle".

Fetching Updates

Remember that we hadn't grabbed the absolute latest, greatest ROMS. We want to go back to the master branch to bring it in, but first, it's always good practice to make sure there are no stray files lying around:

% git status
# On branch circle
nothing to commit (working directory clean)

Now we can go back to the master branch and fetch the updates:

% git checkout master
% git svn rebase

A rebase is a reordering of the commits, in this case putting our changes after the history that's coming from the svn repository:

First, rewinding head to replay your work on top of it...
Applying: adding .gitignore

In this case, I want to keep the master branch as a clean copy of the ROMS trunk code (except for that .gitignore).

Merging and a Conflict

We've updated the master branch, but not the circle branch. Let's go take care of that:

% git checkout circle

I can simply show you the merge:

% git merge master

or I can show you a little conflict just for fun. Let's change ROMS/Version to look like:

ROMS/TOMS Framework: January 19, 2011
===================

Copyright (c) 2002-2011 The ROMS/TOMS Group
Licensed under a MIT/X style license
See License_ROMS.txt

svn: $HeadURL$
svn: $LastChangedBy$
svn: $LastChangedRevision$
svn: $LastChangedDate$
svn: $Id$

Notice that the svn stuff like "$HeadURL$" has not been expanded. Some of these tags are read by ROMS, so we can fill in useful information there, for at least the URL and author:

Heck if I'm going to keep the revision number up to date, but go for it if you're so inclined.

Now we're ready for a fun merge:

% git merge master
error: Your local changes to 'ROMS/Version' would be overwritten by merge. Aborting.
Please, commit your changes or stash them before you can merge.

Oops, maybe not quite. Let's do that commit, then try again:

% git commit -a -m "having fun"
% git merge master

We got a conflict message and we can also see the list of troublesome files with:

% git status

Opening this file we see:

<<<<<<< HEAD
ROMS/TOMS Framework: January 19, 2011
=======
ROMS/TOMS Framework: January 18, 2011
>>>>>>> master

Merge conflicts always have the trouble shown between the "<<<<<<<" string and the ">>>>>>>" string, with the "=======" string dividing the two versions. Let's just clean up the mess, leaving Hernan's version and then tell git the problem has been resolved:

% git add ROMS/Version

We can check "git status" again to see that the red file has turned green and we are ready to commit:

% git commit

Conflicts are usually pretty painless, though I know I'm in for some fun merging Hernan's spatially variable bottom drag with my own version of the same feature. However, with git-svn, each change comes in independently and it's easier to isolate the changes. After updating the master, it is possible to literally apply one patch at a time with "git cherry-pick".

Another Branch

Above we said we want a place for our own changes as well as a place for the CIRCLE problem. We want to make the new branch to be a copy of the master branch. The command "git branch name" copies the current branch, so let's go back to master first:

% git checkout master
% git branch my_stuff
% git checkout my_stuff
% git branch

One purpose of this new branch could be for running the Tide_bay application. We have the code over in the circle branch, but it can't be compiled there due to the Bessel function weirdness. Let's fetch it over to this new branch:

% git checkout circle Apps/Tide_bay

We can see the new stuff with:

% git status

Clearly, we want to commit this here:

% git commit -m "Tide_bay setup"

Last Tips

  • Remember to check that "git status" is clean before changing branches.
  • Though a git archive can know about multiple other git repositories, it can only know about one svn site and it has to be set up during the "git svn clone" operation.
  • Side by side directories can each point to different svn sites and be a "git remote" of the other (as discussed here [4]).