Quick Start: Efficient svn Subcommands in bash

Quick Start: Efficient svn Subcommands in bash

OK we’ve got the excellent Subversion docs and man bash and if you are the bash guru and Subversion expert, you know very well how to combine these to get every job done. All others struggling with whatever is beyond cd and ls in terminal app but don’t want to pay for SmartSVN or whatever will get some tips and tricks. Focus of this article is not the 500th description of the most important commands from both worlds. Instead I am going to show you how to quickly improve your day to day tasks without having to know too much about the background.

Getting Started

I am assuming that you already know the very basic commands in bash like ls, cd, cp, mv, rm, mkdir, man, If not, look at resources section at the end of this posting or try either ls –help or man ls (space to page down q to quit).

The same applies for svn subcommands like help, stat, add, commit, update and import.

I am fine with the vi editor but most of you will hate it. So the first step is configuring bash’s editor from vi to the standard MacOS text editor:

sudo cp /etc/bashrc /etc/bashrc.backup

sudo /Applications/TextEdit.app/Contents/MacOS/TextEdit /etc/bashrc

Look if there is an entry export EDITOR=… and replace it or insert
export EDITOR=/Applications/TextEdit.app/Contents/MacOS/TextEdit

If you like, you can add the alias
alias e=’$EDITOR’

Now you just have to type e myfile.txt to open myfile.txt in text editor. Note that changes made to .bashrc will not be available immediately but in the next terminal session you start (try CMD+T to open a new bash tab)

Ignoring files with svn:ignore

Often there are temporary or other files created that you don’t want to be under version control. Blender for example creates backup files MyModel.blend1, .blend2,… and if Unity3D detects them it adds MyModel.blend1.meta. Therefore you can tell Subversion to to ignore them using the svn:ignore property.

svn propedit svn:ignore .
In the editor list all the files and file name patterns you like to exclude.  In our above Blender / Unity3D example you would enter:
*.blend[0-9] *.blend[0-9]

Save this. Now Subversion won’t bother you any longer with trying to add theses files. You can edit your svn ignores by typing svn propedit svn:ignore . propedit cannot be used recursively. If you want to apply these settings recursively, you can use svn propset command. Note that this will overwrite former edits made in a directory. To apply more than one ignore pattern on the command line we use:
svn propset -R svn:ignore “*.blend[0-9] *.blend[0-9]
” .

Every single pattern must be in its own line. The closing quote indicate the end of the file pattern list and expects the directory to apply to as last parameter.

Tuning svn stat for Bulk Operations

A typical output of svn stat shows us something like:

M       Assets/Scripts/ModifiedFile_1.cs
M       Assets/Scripts/ModifiedFile_2.cs
D       Assets/Scripts/RegularlyDeletedFile.cs

?       Assets/Scripts/NewFile_1.cs
?       Assets/Scripts/SubDir/NewFile_2.cs
!       Assets/Scripts/SubDir/ManuallyDeletedFile.cs

?       Assets/Scripts/Player/NewFile_3.cs
M       Library/ModifiedFile_3.asset

All files marked with ? need to be added to Subversion first before they can be committed. Do this manually for every single file is a boring task so let’s delegate this to Bash. What we need is a filtered list of all files that are not yet under version control. This can be accomplished by piping the output to the grep command. We tell grep to show only files that have a question mark at the beginning of the line:

svn stat | grep -e “^\? ”
?       Assets/Scripts/NewFile_1.cs
?       Assets/Scripts/SubDir/NewFile_2.cs
?       Assets/Scripts/Player/NewFile_3.cs

In order to use this list for a bulk addition we need to format the list to not contain the question mark at the beginning. Because the output is standardised in that it contains one character for the status and then 7 blanks, we can just cut the first 8 characters:

svn stat | grep -e “^\? ” | cut -c 9-

Finally we tell svn add to use this list as input with so called “command substitution”. Everything that is enclosed in grave accents ’ will be executed first and than its output is taken for further processing. Let’s do a harmless non-writing operation like ls first for testing if it works as expected. Note that you must have at least one file in state ? otherwise ls gets an empty output as parameter and just shows the content of the current directory.

ls`svn stat | grep -e “^? ” | cut -c 9-`

Looks pretty good, we are ready to go:

svn add`svn stat | grep -e “^? ” | cut -c 9-`
Adding         Assets/Scripts/NewFile_1.cs
Adding         Assets/Scripts/SubDir/NewFile_2.cs
Adding         Assets/Scripts/Player/NewFile_3.cs

Basically we are ready but … “one more thing” 🙂 Typing this monster chain of commands is definitely not what I call convenient. Do you remember this alias thing from the Getting Started section? That’s what we are looking for to make it a smooth workflow. Open your /etc/bashrc in the editor and add another alias:

alias svnnew=’svn stat | grep -e “^? ” | cut -c 9-‘

Save and exit, open a new bash and go to your source directory. Now svnnew displays all files not yet under version control and svn add `svnnew`will add them to Subversion. For convenience I suggest some more alias definitions for modified and missing files. Add to bashrc:

alias svnmod=’svn stat | grep -e “^M ” | cut -c 9-‘
alias svntrouble=’svn stat | grep -e “^! ” | cut -c 9-‘

BTW missing files can be fixed by svn remove `svntrouble`. Afterwards you have to svn update and to be ready to commit.

Play around with the commands and define aliases you need often. For combining multiple statuses you use brackets within the regular expression, e.g. grep -e “^[?AM] ” will show added, modified and not yet added files.

As noticed in a comment on reddit this solution fails on file/directory names containing a blank, a case that I didn’t have run into until now because I avoid blanks in source files or other assets. While svnnew, etc. work fine when called directly, they will fail on command substitution and there is no trivial solution to this or at least none I know.

A convenient workaround would be to add all files recursively by svn –force –depth infinity add . after you have checked with svnnew that there is no temporary file in the list.

Alternative: 2nd Computer Running Linux Or Windows

Although you can do everything in Subversion from the command line, there might be some complex situations where you prefer the GUI WYSIWIG thing for convenience. If you have a 2nd computer running Linux or Windows, you can optionally share your directory and use open source GUIs like Tortoise SVN or KDE SVN Client. At home I only run Linux because I used to work on Windows all day long when doing projects at the customer site and I like diversity. To do an SMB mount manually on the command line under Linux you can for example type:

sudo mount -t cifs -o user=kay,uid=kay //mymac/MacDevelopmentShare /home/kay/MountedDevelopmentShare

Now in Dolphin you will have access to SVN commands when staying in MountedDevelopmentShare or its child directories. Further on you can use powerful KDE or Gnome SVN clients to perform expert operation.

For unmounting simply type sudo umount /home/kay/MountedDevelopmentShare.

If you don’t have a 2nd computer, a VirtualBox installation of Linux might be an alternative


I hope this little tutorial helped you to get an idea of the power of bash and svn. If you have any suggestions feel free to drop a comment. If you are interested in automating more stuff, I suggest you take a closer look at the reference manuals:


Comments are closed.

Durch die weitere Nutzung der Webseite stimmen Sie der Verwendung von Cookies zu <a href="https://www.scio.de/ueber-uns/scio-impressum/">Mehr</a><br/>By continuing to use the site, you agree to the use of cookies. More

The cookie settings on this website are set to "allow cookies" to give you the best browsing experience possible. If you continue to use this website without changing your cookie settings or you click "Accept" below then you are consenting to this.