diff --git a/core/utils.py b/core/utils.py
index 7259bae..924dac3 100644
--- a/core/utils.py
+++ b/core/utils.py
@@ -31,6 +31,8 @@ troggle.utils.TROG
 chaosmonkey(n) - used by survex import to regenerate some .3d files
 save_carefully() - core function that saves troggle objects in the database
 
+various git add/commit functions that need refactoring together
+
 '''
 
 TROG = {
@@ -57,14 +59,16 @@ def get_process_memory():
     return usage[2]/1024.0 
 
 def chaosmonkey(n):
-    # returns True once every n calls - randomly
+    '''returns True once every n calls - randomly'''
     if random.randrange(0,n) != 0:
         return False
     # print("CHAOS strikes !", file=sys.stderr)
     return True
 
-# handles url or file, so we can refer to a set of scans (not drawings) on another server
+# 
 def GetListDir(sdir):
+    '''handles url or file, so we can refer to a set of scans (not drawings) on another server
+    '''
     res = [ ]
     if type(sdir) is str and sdir[:7] == "http://":
         # s = urllib.request.urlopen(sdir)
@@ -79,8 +83,37 @@ def GetListDir(sdir):
             res.append((f, ff, os.path.isdir(ff)))
     return res
 
+def only_commit(fname, message):
+    '''Only used to commit a survex file edited and saved in view/survex.py
+    '''
+    git = settings.GIT
+    cwd = fname.parent
+    filename = fname.name
+    #print(f'{fname=} ')
+
+    try:
+        cp_add = subprocess.run([git, "add", filename], cwd=cwd, capture_output=True, text=True)
+        if cp_add.returncode != 0:
+            msgdata = f'Ask a nerd to fix this problem in only_commit().\n\n{cp_add.stderr}\n\n{cp_add.stdout}\n\nreturn code:{str(cp_add.returncode)}' 
+            raise WriteAndCommitError(f'CANNOT git on server for this file {filename}. Edits saved but not added to git.\n\n' + msgdata)
+
+        cp_commit = subprocess.run([git, "commit", "-m", message], cwd=cwd, capture_output=True, text=True)
+        # This produces return code = 1 if it commits OK, but when the repo still needs to be pushed to origin/expoweb
+        if cp_commit.returncode != 0 and cp_commit.stdout != 'nothing to commit, working tree clean':
+            msgdata = f'Ask a nerd to fix this problem in only_commit().\n\n{cp_add.stderr}\n\n{cp_add.stdout}\n\nreturn code:{str(cp_add.returncode)}' 
+            print(msgdata)
+            raise WriteAndCommitError(f'Error code with git on server for this file {filename}. Edits saved, added to git, but NOT committed.\n\n' + msgdata)
+
+    except subprocess.SubprocessError:
+        raise WriteAndCommitError(f'CANNOT git on server for this file {filename}. Subprocess error. Edits not saved.\nAsk a nerd to fix this.')
+
 def write_and_commit(files, message):
-    """Writes the content to the filepath and adds and commits the file to git.  If this fails, a WriteAndCommitError is raised."""
+    """Writes the content to the filepath and adds and commits the file to git.  If this fails, a WriteAndCommitError is raised.
+    This does not create any needed intermediate folders, which is what we do when writing survex files, so functionality here
+    is duplicated in only_commit()
+    
+    These need refactoring
+    """
     git = settings.GIT
     try:
         for filepath, content, encoding in files:
diff --git a/core/views/expo.py b/core/views/expo.py
index 2a4c1c7..cf17346 100644
--- a/core/views/expo.py
+++ b/core/views/expo.py
@@ -16,13 +16,11 @@ from django.contrib import admin
 
 import django.forms as forms
 
-from .auth import login_required_if_public
-from troggle.core.models.caves import Cave
 import troggle.core.views.caves
 import troggle.settings as settings
-
+from .auth import login_required_if_public
+from troggle.core.models.caves import Cave
 from troggle.core.utils import write_and_commit, WriteAndCommitError
-
 from troggle.core.views.editor_helpers import HTMLarea
 
 
diff --git a/core/views/survex.py b/core/views/survex.py
index caeaba6..c07ce2d 100644
--- a/core/views/survex.py
+++ b/core/views/survex.py
@@ -18,6 +18,7 @@ from troggle.core.models.troggle import Expedition, Person, PersonExpedition
 from troggle.core.models.survex import SurvexBlock, SurvexPersonRole, SurvexFile, SurvexDirectory
 from troggle.core.models.caves import Cave, PersonTrip, LogbookEntry
 from troggle.parsers.people import GetPersonExpeditionNameLookup
+from troggle.core.utils import only_commit, WriteAndCommitError
 
 '''Everything that views survexfiles 
 but also displays data on a cave or caves when there is ambiguity
@@ -124,6 +125,7 @@ class SvxForm(forms.Form):
             svxtext = fin.read() 
             fin.close()
         except:
+            # hack. Replace this with something better.
             fin = open(fname, "r",encoding='iso-8859-1',newline='')
             svxtext = fin.read() 
             fin.close()
@@ -163,9 +165,9 @@ class SvxForm(forms.Form):
         res = fout.write("\n")
         fout.close()
         
-        # INSERT code to do git add and commit here, to loser repo. When Wookey chnages :loser: to use git.
+        only_commit(fname, f"Online survex edit: {self.data['filename']}.svx")
         
-        return "SAVED"
+        return "SAVED and committed to git"
 
     def Process(self):
         print(">>>>....\n....Processing\n")