I have been slowly evolving some code for Git and VSS interop based on a quest I started a while ago
And the code is now working, some parts have been updated without test (such as the init) and I am not 100% sure everything is doing what it should/is the best way and some parts seem really round the houses!
Its certainly past the point where it needs some input.
The basic concept is
- "Pulling" from source safe is achieved by keeping a separate "vss_branch"
- vss_branch is kept up to kept up to date with source safe via a full source safe get
- master treats vss_branch as its "upstream/origin" so master pulls from vss_branch
- "Pushing" to source safe
- is achieved by figuring out what is different between master and vss_branch
- saving and then pushing to vss_branch
- then I go through all the modified/deleted/added files, and applying the appropriate operation e.g. checking them out and checking them in
The code is currently used in the context of git, vss, beyondcompare and trackgear
I am keeping an up to date version here:
Code at time of question:
#--useful aliases
alias gitremove="git ls-files --deleted -z | xargs -0 git rm"
alias bcompare="START / \"C:\Program Files (x86)\Beyond Compare 3\BCompare.exe\""
alias initgitss=InitGitAndSourceSafeProject
alias ssclone="ss get "$CURRENT_SOURCE_SAFE_PROJECT" -W -R -Q -Y$SSNAME -I-N"
alias ssdiff="ss Diff -Y$SSNAME"
#----These Need Setting:
##Your source safe project
CURRENT_SOURCE_SAFE_PROJECT=
##You Working directory
CURRENT_PROJ_DIR=
#--For Source Safe Comments
ACTIVE_TRACK_REF=
PROJECT_NAME=
##Your BeyondCompare Session
#its better to create a beyond compare session so you can set it up how you like
BEYOND_COMPARE_SESSION=
#----SysVars
REF_APPEND="_REF"
#--variable set up helper
sset()
{
if [ $# -eq 0 ]
then
echo "No arguments supplied, please supply the SS project name"
fi
CURRENT_SOURCE_SAFE_PROJECT=$1
CURRENT_PROJ_DIR=$(pwd)
}
#--create a git project from a VSS project and set everything up ---#
InitGitAndSourceSafeProject()
{
if [ -z ${CURRENT_SOURCE_SAFE_PROJECT+x} ];
then echo "CURRENT_SOURCE_SAFE_PROJECT is unset";
exit;
fi
git init
#get all the SS sourcecode
echo "Switching to $CURRENT_SOURCE_SAFE_PROJECT"
ss cp $CURRENT_SOURCE_SAFE_PROJECT
ssclone
git add --all
git commit -m "Initial Source Safe Clone"
#create fake upstream
git checkout -b vss_branch
#create a dev branch
git checkout -b dev
git checkout master
#set master to treat "vss_branch" as upstream
git branch --set-upstream-to vss_branch
SynchMasterToSS
}
#---reset to current project---#
sreset()
{
echo "Make sure we are in the correct source safe project"
ss CP $CURRENT_SOURCE_SAFE_PROJECT
ss project
}
quietsreset()
{
ss CP $CURRENT_SOURCE_SAFE_PROJECT -O-
}
#----Commit *one file* -that is already added- to SS----#
sscommitone()
{
FULLPATH=$1
DIR=$(echo ${FULLPATH%/*})
SS_COMMENT="$PROJECT - TGR: $TGR\n\n"
#go to correct place in working directory
pushd $DIR
#checkout file without overwriting local copy
#echo Y | ss checkout "$FULLPATH" -G-WR -Y$SSNAME
ss checkout "$FULLPATH" -G-WR -Y$SSNAME -I-Y
#check in the file with comment
#echo Y | ss checkin "$1" -C"$SS_COMMENT" -W -Y$SSNAME
ss checkin "$1" -C"$SS_COMMENT" -W -Y$SSNAME -I-Y
#go back to the directoy we were in -root-
popd
}
#----bulk commit---#
sscommit()
{
for file in $1; do
sscommitone $file
done
}
#----bulk add-----#
AddEachNewFile()
{
printf "\n\nAdding files requires us to loop, so we can add to the correct directory"
for file in $1; do
printf "\n--Resetting Dir---\n"
quietsreset
new_file=$(echo ${file##*/})
directory=$(echo ${file%/*})
#cp to folder
echo "Directory is: $directory"
quietsreset
test=$(ss CP $directory 2>&1 | grep -c 'exist' 2>&1)
if (( "1"== $test ));
then
echo "Did not to find directory! It does not exist!....yet :)";
new_directory=$directory;
last_directory=$directory;
while (( "1"== $test ));
do
echo "->This parent directory does not exist, try going up";
echo "---trying to cp to $new_directory"
last_directory=$(echo ${new_directory})
new_directory=$(echo ${new_directory%/*})
quietsreset
test=$(ss CP $new_directory 2>&1 | grep -c 'exist' 2>&1)
echo "[+]"
done
echo "Directory does not exit, need to add $last_directory";
ss Add $last_directory -R -C"$SS_COMMENT" -Y$SSNAME
else
echo "Directory already exist, need to add file: ${file}";
ss Add $file -C"$SS_COMMENT" -Y$SSNAME
fi
done
}
#use this function for when you forgot to fill in TGR info
ptgr()
{
updateModDelAddVars $1
printTGRInfo
}
#--- vars needed for to perform ss operations ----
updateModDelAddVars()
{
#files to check out and in again from SS
MODIFIED_FILES=$( git diff --name-only $1 --diff-filter=M)
#files to add to SS
ADDED_FILES=$( git diff --name-only $1 --diff-filter=A)
#file to delete from SS
DELETED_FILES=$( git diff --name-only $1 --diff-filter=D)
}
printTGRInfo()
{
printf "Please update the TGR with the following changed files:"
printf " \n***********************\n"
printf "|--Modified Files --\n\n"
printf "$MODIFIED_FILES"
printf " \n--\n"
printf "|--New Files --\n\n"
printf "$ADDED_FILES"
printf " \n--\n"
printf "|--Deleted Files --\n\n"
printf "$DELETED_FILES"
printf " \n\n ********************* \n"
}
##------Pull -todo- find out what other command is assigned to sspull!
sspullb()
{
if [ ! -d ".git" ]; then
echo "Must be ran from root git/ss rep"
exit;
fi
#save branch we are on
BRANCH=$(git symbolic-ref HEAD | sed -e 's,.*/\(.*\),\1,')
#jump to "fake upstream"
git checkout vss_branch
#update vss branch to match vss..
echo "grabbing all files from sourcesafe"
ssclone
##figure out files I have changed
FILES=$( git diff --name-only master vss_branch)
##grab the recent history for those files & everything else seperately
NOW=$(date)
SSFILEHISTORY=$(ss History . $FILES -#3)
SSHISTORY=$(ss History . -#3)
##now add & commit those files with a comment
git add --all
MESSAGE=$(echo -e "Source safe sync: $NOW \n Changes to my files: \n $SSFILEHISTORY \nChanges To Other Files:\n $SSHISTORY")
git commit -a -m"$MESSAGE"
#jump back to branch that wants to pull
git checkout $BRANCH
git pull
}
##------ 'Push'
sspush()
{
if [ ! -d ".git" ]; then
echo "Must be ran from root git/ss rep"
exit;
fi
BRANCH=$(git symbolic-ref HEAD | sed -e 's,.*/\(.*\),\1,')
##-TODO- check for git error at checkout attempt instead!
##we might have some work uncommitted (naughty)
##git stash
#get a suitable amount of git master comments for SS comment SS comment IS limted to 500chars though...
GIT_COMMENT=$(git log --pretty=format:"%h %s" --no-merges -n 3)
git log --no-merges > fullGitHistory.githistory
#figure out files that need to go into source safe
updateModDelAddVars vss_branch
#ok now make vss_branch up to date -this keeps git happy :)-
#the odd syntax is due to the fact we are treating vss_branch as our upstream
git push . HEAD:vss_branch
#check the file in with latest git comments but keep files as writeable
#--TODO-- read -p "Please enter the TGR this commit relates to: " TGR
TGR=$ACTIVE_TRACK_REF
#Add each file (and possible directory)
printf "\n---------------------------------------------------\n"
printf "Adding new files \n->\n $ADDED_FILES"
printf "\n---------------------------------------------------\n"
SS_COMMENT="$PROJECT - TGR: $TGR \n\n$GIT_COMMENT"
AddEachNewFile $ADDED_FILES
printf "\n---------------------------------------------------\n"
printf "Deleting old files \n->\n $DELETED_FILES"
printf "\n---------------------------------------------------\n"
ss Delete $DELETED_FILES -Y$SSNAME -I-N
#Loop through the files, checking in and out from correct directory
printf "\n---------------------------------------------------\n"
printf "Overwriting modified files \n->\n $MODIFIED_FILES"
printf "\n---------------------------------------------------\n"
sscommit $MODIFIED_FILES
#update git history file -this way SS has all the rich comment history I store with git despite SS's 500 comment character limit-
ss Add fullGitHistory.githistory -C"Log of all git history"
sscommitone fullGitHistory.githistory
#now print the message needed for the TGR comment
printTGRInfo
#"unpop" all the things we just did to restore working tree
git checkout $BRANCH
##--TODO-- check for git error at checkout attempt instead!
##git stash apply
}
#replace Source-safe code with my master branch code
masterpushss()
{
echo "to master branch"
git checkout master
sspush
}
#merge master with source safe code
masterpullss()
{
git checkout master
sspullb
}
#get master to perform pull and push
synch()
{
masterpullss
masterpushss
}
##----True Diff---
hardrefupdate()
{
REF_FOLDER="$CURRENT_PROJ_DIR$REF_APPEND"
rm -rf $REF_FOLDER
updateref
}
updateref()
{
REF_FOLDER="$CURRENT_PROJ_DIR$REF_APPEND"
if [ ! -d $REF_FOLDER ]; then
mkdir $REF_FOLDER
fi
pushd $REF_FOLDER
ssclone
popd
}
compare_toREF()
{
if [ -z "$BEYOND_COMPARE_SESSION" ]; then
bcompare $CURRENT_PROJ_DIR $REF_FOLDER /iu /filters="-*.scc;-*.opensdf;-*.sdf;-*.orig" /qc=size
else
bcompare $BEYOND_COMPARE_SESSION
fi
}
#should only be needed for sanity checks -diff with vss_branch *should* achieve the same-
diffallss()
{
if [ -z ${CURRENT_PROJ_DIR+x} ];
then echo "CURRENT_PROJ_DIR is unset";
exit;
fi
UpdateRef
compare_toREF
}
harddiffallss()
{
if [ -z ${CURRENT_PROJ_DIR+x} ];
then echo "CURRENT_PROJ_DIR is unset";
exit;
fi
hardrefupdate
compare_toREF
}
#PS1='[\u@\h`__git_ps1` \W]\$