ROMS git: Difference between revisions
No edit summary (change visibility) |
|||
(2 intermediate revisions by one other user not shown) | |||
Line 4: | Line 4: | ||
==What is git?== | ==What is git?== | ||
Git is a distributed version control system available from [http://git-scm.com/]. That site also contains links to documentation and other resources - | Git is a distributed version control system available from [http://git-scm.com/]. That site also contains links to documentation and other resources, including the fabulous [https://git-scm.com/book/en/v2 Pro Git] book. I have also written about it [https://www.myroms.org/wiki/index.php/File:Git.pdf here] and on the [https://www.myroms.org/blog/ ROMS blog]. As git is 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. | 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. | ||
Line 35: | Line 35: | ||
===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 | <div class="box">% git svn –r 526 clone --username name <nowiki>https://www.myroms.org/svn/src/trunk</nowiki> [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: | ||
<div class="box">[core]<br /> repositoryformatversion = 0<br /> filemode = true<br /> bare = false<br /> logallrefupdates = true<br /> ignorecase = true<br />[svn-remote "svn"]<br /> url = https://www.myroms.org/svn/src/trunk<br /> fetch = :refs/remotes/git-svn</div> | <div class="box">[core]<br /> repositoryformatversion = 0<br /> filemode = true<br /> bare = false<br /> logallrefupdates = true<br /> ignorecase = true<br />[svn-remote "svn"]<br /> url = <nowiki>https://www.myroms.org/svn/src/trunk</nowiki><br /> fetch = :refs/remotes/git-svn</div> | ||
===Ignoring Files=== | ===Ignoring Files=== | ||
Line 79: | Line 79: | ||
<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 information 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: <nowiki>$https://www.myroms.org/svn/src/trunk/$</nowiki><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. | ||
Now we're ready for a fun merge: | Now we're ready for a fun merge: | ||
Line 113: | Line 113: | ||
<div class="box">% git svn rebase</div> | <div class="box">% git svn rebase</div> | ||
This fetches the changes since last time, however long I've let it go. Ideally, I'd do a "git log" first to see where things stood before. Now I'll do it after: | This fetches the changes since last time, however long I've let it go. Ideally, I'd do a "git log" first to see where things stood before. Now I'll do it after: | ||
<div class="box">% git log<br />commit 5d4b1e87f84c76e424567cf672a30b7b1623d315<br />Author: arango <arango@f091316a-d328-0410-a40a-876eff57d070><br />Date: Tue Jan 18 16:38:32 2011 +0000<br /><br /> src:ticket:483<br /> <br /> git-svn-id: https://www.myroms.org/svn/omlab/branches/arango@1361 f091316a-d<br /><br />commit 91a7542ec4e99ca44b340600af3c63519c8f1d35<br />Author: arango <arango@f091316a-d328-0410-a40a-876eff57d070><br />Date: Fri Jan 14 21:33:39 2011 +0000<br /><br /> src:ticket:482<br /> <br /> git-svn-id: https://www.myroms.org/svn/omlab/branches/arango@1358 f091316a-d<br /><br />commit 2445e4e62f73f54115d2d16c69d6be093b56b0ea<br />Author: arango <arango@f091316a-d328-0410-a40a-876eff57d070><br />Date: Thu Jan 6 19:40:42 2011 +0000<br /><br /> src:ticket:481</div> and so on... In this case I can tell by dates which commits are new to me, since I last merged sometime between the Dec 2 and the Dec 30 commits. That brings the arango directory up to date. | <div class="box">% git log<br />commit 5d4b1e87f84c76e424567cf672a30b7b1623d315<br />Author: arango <arango@f091316a-d328-0410-a40a-876eff57d070><br />Date: Tue Jan 18 16:38:32 2011 +0000<br /><br /> src:ticket:483<br /> <br /> git-svn-id: <nowiki>https://www.myroms.org/svn/omlab/branches/arango@1361</nowiki> f091316a-d<br /><br />commit 91a7542ec4e99ca44b340600af3c63519c8f1d35<br />Author: arango <arango@f091316a-d328-0410-a40a-876eff57d070><br />Date: Fri Jan 14 21:33:39 2011 +0000<br /><br /> src:ticket:482<br /> <br /> git-svn-id: <nowiki>https://www.myroms.org/svn/omlab/branches/arango@1358</nowiki> f091316a-d<br /><br />commit 2445e4e62f73f54115d2d16c69d6be093b56b0ea<br />Author: arango <arango@f091316a-d328-0410-a40a-876eff57d070><br />Date: Thu Jan 6 19:40:42 2011 +0000<br /><br /> src:ticket:481</div> and so on... In this case I can tell by dates which commits are new to me, since I last merged sometime between the Dec 2 and the Dec 30 commits. That brings the arango directory up to date. | ||
I now go to my svn_src directory. I already told it that the arango directory is a remote, but I need to update its view of it: | I now go to my svn_src directory. I already told it that the arango directory is a remote, but I need to update its view of it: |
Latest revision as of 13:08, 1 November 2018
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, including the fabulous Pro Git book. I have also written about it here and on the ROMS blog. As git is 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 1.7.1 (svn 1.6.5)
If everything is there and you are not in a git sandbox, you get this instead:
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:
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.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:
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:
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:
Build
ocean?
core*
We can add this to the list of files to be tracked by git:
% 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 checkout circle
% git branch
This last command should just show that we are now in the circle branch:
master
Now to fetch the circle code from [3]. From the trunk directory, we can apply these changes to the circle branch:
% patch -p1 < Circle.diffs
We can see what we have with "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:
Now we can commit the whole works:
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:
# On branch circle
nothing to commit (working directory clean)
Now we can go back to the master branch and fetch the updates:
% 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:
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:
I can simply show you the merge:
or I can show you a little conflict just for fun. Let's change ROMS/Version to look like:
===================
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:
svn: $arango$
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:
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 merge master
We got a conflict message and we can also see the list of troublesome files with:
Opening this file we see:
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:
We can check "git status" again to see that the red file has turned green and we are ready to 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 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:
We can see the new stuff with:
Clearly, we want to commit this here:
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]).
Cherry-picking Notes
I was asked for more on "git cherry-pick". Here's an example in two directories, one pointing to an Hernan repo, one pointing to my svn branch. Over in the arango directory:
This fetches the changes since last time, however long I've let it go. Ideally, I'd do a "git log" first to see where things stood before. Now I'll do it after:
commit 5d4b1e87f84c76e424567cf672a30b7b1623d315
Author: arango <arango@f091316a-d328-0410-a40a-876eff57d070>
Date: Tue Jan 18 16:38:32 2011 +0000
src:ticket:483
git-svn-id: https://www.myroms.org/svn/omlab/branches/arango@1361 f091316a-d
commit 91a7542ec4e99ca44b340600af3c63519c8f1d35
Author: arango <arango@f091316a-d328-0410-a40a-876eff57d070>
Date: Fri Jan 14 21:33:39 2011 +0000
src:ticket:482
git-svn-id: https://www.myroms.org/svn/omlab/branches/arango@1358 f091316a-d
commit 2445e4e62f73f54115d2d16c69d6be093b56b0ea
Author: arango <arango@f091316a-d328-0410-a40a-876eff57d070>
Date: Thu Jan 6 19:40:42 2011 +0000
src:ticket:481
and so on... In this case I can tell by dates which commits are new to me, since I last merged sometime between the Dec 2 and the Dec 30 commits. That brings the arango directory up to date.
I now go to my svn_src directory. I already told it that the arango directory is a remote, but I need to update its view of it:
This pulls over information from the arango repo into the local repo. The remotes I'm tracking can be viewed:
* kate_svn
master
remotes/arango/master
remotes/cygnus/kate_svn
remotes/cygnus/master
Now I can pull the changes over one at a time and deal with any conflicts as they arise:
with the "4a4..." being the start of the SHA1 number corresponding to the commit I'm fetching over. Some come cleanly, some do not:
mark the corrected paths with 'git add <paths>' or 'git rm <paths>'
and commit the result with:
git commit -c 4a46a1098e96a5
I can see which files to clean up with "git status":
# (use "git reset HEAD <file>..." to unstage)
# (use "git add/rm <file>..." as appropriate to mark resolution)#
# both modified: ROMS/Nonlinear/main3d.F
# both modified: ROMS/Nonlinear/set_avg.F
# both modified: ROMS/Utility/wrt_avg.F
# both modified: ROMS/Utility/wrt_his.F
Just as in the merge conflict, I need to go into each file, then tell git that all is well with that file:
That file will now show up in green instead of red in the "git status" report. Once all conflicted files are clear, it is safe to "git commit" and accept the merge message it brings up. If the cherry-pick is clean, the commit happens automatically and "git status" shows the all clear.