NOTE:  When generating lists of git commits to compare against an SVN list, do so *before*
archiving the branches that aren't active in SVN.  The git logging mechanisms will ignore
commits now active only in the history of the tag that has archived the branch, and will
look like "dropped" commits in a comparison.  The below script is an attempt to get a
better list:

#!/bin/sh
# Use a trick from https://stackoverflow.com/a/47947423
git cat-file --batch-check --batch-all-objects |grep commit | awk '{print "git log -1 --pretty=format:\"%H %s%n\" " $1}' > print_all_msgs.sh
bash print_all_msgs.sh > all_msgs.txt
cat all_msgs.txt|grep -v Note\ SVN\ revision > all_non_note_msgs.txt
awk '{print "git log -1 --pretty=format:\"GITMSG%n%H,%ct +0000,%B%nGITMSGEND%n\" " $1}' all_non_note_msgs.txt > print_msgs.sh
bash print_msgs.sh > git.log
rm print_all_msgs.sh all_msgs.txt all_non_note_msgs.txt print_msgs.sh
#rm all_msgs.txt all_non_note_msgs.txt

(Also worth noting - preliminary move commits have the same timestamp as their
child commit, so they get chosen as that timestamp's commit line and the
subsequent (identical) commit with it's message doesn't make the list.  The
commits are there, but not (currently) written out by the svn_msg.cxx code...)

The following command will be useful:

git fsck --lost-found

A git show on the resulting sha1 objects (or at least the commit objects) will identify
problems we might have introduced.  When doing archive_branches.sh, do so on a copy and
then run the above command.  See what has been lost (a preliminary test shows a number
of dangling commits and blobs) and figure out what we should do instead to avoid having
them become dangling.  I suspect (but haven't proven yet) that the ambiguous naming warnings
from that script mean we archived the tag commit and not the actual branch commit - probably
need to do full specification of refs/heads in the archiving script so we don't grab the
tags instead:  https://softwareengineering.stackexchange.com/a/378232


NOTE:  When building new logic with Git, we're assuming a modern version (work is being done with
2.17.1.)  1.7 is known to be too old for most of the git notes based tricks below to work, and
it's likely that other features used in distcheck will prompt either a version based test or
some kind of feature check to make sure a new enough git is present on the system for things
to function as expected.


TODO:  We'll need to look at protecting branches from deletion, i.e.
https://help.github.com/en/articles/configuring-protected-branches
https://gist.github.com/pixelhandler/5718585
https://stackoverflow.com/questions/48381923/how-can-i-prevent-deletion-of-remote-branches-in-pure-git
https://stackoverflow.com/questions/19293222/how-to-prevent-remote-branch-deletion-in-git-without-using-gitolite

May also want style-based enforcement at some point:
https://github.com/barisione/clang-format-hooks
https://github.com/mellowcandle/astyle_precommit_hook
https://github.com/Sarcasm/run-clang-format

Possibly useful notes for OSX/Windows users:
https://stackoverflow.com/questions/8904327/case-sensitivity-in-git


################# .gitconfig helpers ###################

Here is a simple way to use notes with svn revision numbers to checkout a specific revision:

git log --all --pretty=format:"%H %N" --grep svn:revision:29886|awk '{system("git checkout "$1)}'

To make this easier, add the following alias to your .gitconfig file:

	svnrev = "!f() { \
		if [ x$1 != x ] ; then \
                   REVSHA1=\"$(git log --all --pretty=format:\"%H %N\" --grep svn:revision:$1$)\"; \
                   REVSHA1N=$(echo $REVSHA1 | awk '{print $1}'); \
                   if [ x$REVSHA1N != x ] ; then \
                      git checkout $REVSHA1N; \
		   else \
		      echo Unknown revision number: $1; \
		   fi; \
		else \
		   echo Need revision number; \
		fi; \
		}; f"

With that alias in place, the command "git svnrev 29886" will check out the git
commit with a not matching the pattern "svn:revision:29886"


In svn, we can svn log in a particular branch checkout to see the history
specific to that branch, but this is apparently a challenge in git.  The
following logic added to your .gitconfig defines a logb command that will list
commits unique to either the currently checked out branch (if you don't supply
a branch name) or the specified branch if you specify one. (This packages up
the tricks from https://stackoverflow.com/q/14848274 and
https://stackoverflow.com/a/12142066)

        logb = "!f() { \
                if [ x$1 != x ] ; then \
                   CURRBRANCH=$1; \
                else \
                   CURRBRANCH=\"$(git rev-parse --abbrev-ref HEAD)\"; \
                fi; \
                HAVEBRANCH=$(git rev-parse --verify --quiet $CURRBRANCH); \
                HAVEABRANCH=$(git rev-parse --verify --quiet archived/$CURRBRANCH); \
		if [ -z $HAVEBRANCH ] && [ ! -z $HAVEABRANCH ] ; then \
                   echo \"Branch $CURRBRANCH is not current - to see archived branch history, specify archived/$CURRBRANCH\" ; \
                else \
                   git log $CURRBRANCH --not $(git for-each-ref --format='%(refname)' refs/heads/ | grep -v \"refs/heads/$CURRBRANCH\"); \
                fi ; \
                }; f"

The above report is limited by git's knowledge of branch history, which will not
always match SVN's (the history of the bullet branch is an example).  To print
the SVN record of the branch, use the following alias:

        logsvnb = "!f() { \
                if [ x$1 != x ] ; then \
                   CURRBRANCH=$1; \
                else \
                   CURRBRANCH=\"$(git rev-parse --abbrev-ref HEAD)\"; \
                fi; \
                git log --all --show-notes --grep=\"svn:branch:$CURRBRANCH$\"; \
                }; f"

####################  Establishing identities  ###############################

For users who want to set up brlcad git repositories to use their github
username and email but not use those as their default commit ID for all
repositorires on their machine, it is possible to set user name and email on a
per-repository basis from the checkout directory:

git config user.name "Jane Smith"
git config user.email “jsmith@mail”

For those who don't want to have to remember to set this every time they clone
the repository, a feature introduced in Git 2.13 is worth exploring. It is now
possible to use conditional includes to globally specifiy a specific
username/email combination when working in directories that match patterns:

https://stackoverflow.com/a/43654115

############  Other useful tips ##############

Many (most?) of BRL-CAD's commit messages are long one liners - it turns out gitk does have
the ability to word wrap, but (why???) it isn't on by default.  We'll want to advise users
to enable it, per https://stackoverflow.com/questions/35017472/enabling-word-wrap-in-gitk-for-commit-message-display-on-a-mac

May want to investigate conditional includes as well so we can pre-package a repo specific .gitconfig:
https://git-scm.com/docs/git-config#_conditional_includes


# Overview with all branches:

# gitk --branches="*"

# Nifty trick for getting commit counts per committer (https://stackoverflow.com/a/9839491)
# git shortlog -s -n --branches="*"

# Good way to get a quick overview of branch/tag structure:
# tig --all --simplify-by-decoration

###########################################################################
Sean inquired with the Git list, and per Jeff King there may be a way to
preserve notes across a filter branch operation, which is something we
will need/want if we ever have to apply filter-branch to the converted
repository:

https://marc.info/?l=git&m=156653998201710

# Sigh... It seems the (maybe?) in an old commit name causes
# problems for https://github.com/tomgi/git_stats - may need
# to do something along the lines of https://stackoverflow.com/a/28845565
# with https://stackoverflow.com/a/41301726 and https://stackoverflow.com/a/38586928
# thrown in...
#
# Note: experiment only on a COPY doing this rewrite - it is destructive!!!
#
# Also note:  Once you do the below step, svnfexport cannot incrementally update
# the repository.  Most of the sha1 hashes will be wrong.  Do this sort of thing ONLY as the
# final step BEFORE the git repository becomes live and AFTER the SVN history is frozen.
#
# git config notes.rewriteRef refs/notes/commits  (see https://stackoverflow.com/a/43785538)
# git checkout 7cffbab2a734e3cf
# GIT_COMMITTER_DATE="Fri Oct 3 06:46:53 1986 +0000" git commit --amend --author "root <root>" --date="Fri Oct 3 06:46:53 1986 +0000"
# git checkout master
# git replace 7cffbab2a73 e166ad7454
# git filter-branch \
           --commit-filter '
		commit=$(git commit-tree "$@")
		git notes copy $GIT_COMMIT $commit
		echo $commit
	  ' \
           --tag-name-filter cat \
           --env-filter 'export GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"' -- --all
# git replace -d 7cffbab2a734e3cf



################################################################################

Uploading to github:

After creating a new repository via the github website:

# Note - the specific version of this line will be provided by github when the repository is created via the website.
git remote add origin git@github.com:brlcad/brlcad.git

# push all branches
git push --all

# push all tags
git push --tags

# push notes
git push origin refs/notes/commits

# We then download it back from github:
git clone git@github.com:brlcad/brlcad.git
cd brlcad
# Verify all the branches and tags are there:
git branch -a
git tag
#When cloning the repo from github, you also have to manually fetch the notes:
git fetch origin refs/notes/commits:refs/notes/commits

To make this automatic, add a section to your .git/config:
https://gist.github.com/topheman/ec8cde7c54e24a785e52

# To pull a backup, use --mirror (this seems to get the notes):
git clone --mirror git@github.com:brlcad/brlcad.git


################################################################################

Unless our checks prove too heavy for the CI system, we should look into using
the available Github built-in CI support for multiple platforms.  Starting
points:

https://github.com/actions/starter-workflows/pull/47
https://github.com/cristianadam/HelloWorld/
https://github.com/marketplace/actions/run-cmake
https://github.com/marketplace/actions/makensis
https://github.com/jurplel/install-qt-action

BRL-CAD's test will likely be quite heavy by normal testing standards,
particularly across multiple platforms, if we're doing the full testing routine
per commit (distcheck-full is virtually guaranteeded to be too much as one
test...)

To avoid straining the github infrastructure, we'll want to look into options
to schedule when our tests are run, so we can get full coverage but not hammer
the system too hard:

https://docs.github.com/en/actions/reference/events-that-trigger-workflows#scheduled-events

We'll need to start simple, with a cron scheduled basic distcheck across
Linux, Windows and Mac, to demonstrate everything works.

One idea is teach the CMake distcheck build setup to generate workflow files
for each distcheck test and a master file to schedule it all, which we could
then just copy into the repo's .github/workflows directory.  Could be managed
the same way the INSTALL and configure files are managed - generated in build
dir, but compile ultimately fails if they differ with the versions in the src
tree.

Longer term, current thought is to investigate building a minimal core subset
(gsh/libged and deps, with some expensive options like GDAL/STEP/docs disable,
for example) per commit, and cron job more expensive tests to run periodically.
Could also look at the caching mechanism to store src/other deps to avoid
rebuilding them, but that might be easier once we get a proper superbuild set
up and can set up per-sub-project-based workflows.  (Need, for example, to
invalidate the cache and rebuild openNURBS if we make a change to our bundled
version, so what we really want is our own openNURBS project generating
artifacts per-change that our main build workflow then grabs and installs as
needed...)

##################################################################################
If we want a "straighter" presentation of the statistics of our git history than
those of Github (which bases its reporting only on commit ids linkable to github
accounts and skips reporting any others) the best tool I've found thus far
looks to be gitstats:

https://github.com/tomgi/git_stats

After installing, statistics pages can be generated by running:

git_stats generate

in a clone of the repository.



Note - on Ubuntu, per https://github.com/rails/rails/issues/34822 I had to add the line:

gem 'bigdecimal', '1.4.2'

to the git_stats file

/var/lib/gems/2.7.0/gems/git_stats-1.0.17/bin/git_stats

and install the older version of bigdecimal (per https://stackoverflow.com/a/17026442):

gem install bigdecimal -v 1.4.2

###############################################################################
SVN ids to revision numbers can be captured as follows to a file:

svn log file:///home/user/brlcad_code | grep "|" | grep "^r[0-9][0-9 ]" | grep -v \(no\ author\) | awk -F "|" '{print $1 $2}' | sed -e 's/r//' | sed -e 's/ $//' | sed -e 's/  / /' > rev_map

This may be enough information pre-notes-merge in repowork to allow us to
assign one additional property - the cvs/svn commit author name.

#############################################################################
A note when running git fast-export - you want to make sure and checkout master
before doing the export - I accidentally did so while in a detached HEAD
state, and ended up with a HEAD branch in the conversion (which completely
messed up gitk).

cd brlcad && git checkout master
git fast-export --all --show-original-ids > ../brlcad.fi


#############################################################################
Other large scale git conversions:
https://web.archive.org/web/20130327012743/https://techbase.kde.org/Projects/MovetoGit
https://techbase.kde.org/Projects/MovetoGit
https://blog.runtux.com/posts/2014/04/18/233/
https://blogs.ed.ac.uk/timc/2017/11/24/migrating-from-svn-to-git-while-splitting-repository/
http://esr.ibiblio.org/?p=5634
http://esr.ibiblio.org/?p=6792
http://esr.ibiblio.org/?p=8607
https://gitlab.com/ideasman42/blender-git-migration/

