Version Control in Gamedev
Hi all,
I've shared the slide deck from Tuesday evening here:
http://www.slideshare.net/mattbenic/source-andassetcontrolingamedev
The Github repo I set up for the ill-fated demo is at:
https://github.com/mattbenic/SourceControlInGameDev
The only thing really worth having in that repo is the .gitignore file, which you can use as a template when prepping your own projects for git. Other than that, those bugs are still in there waiting to be fixed, so feel free to mess around as you like to get used to git :) What I'd really love to see here is people actually trying to use this and posting any issues they run into.
I've shared the slide deck from Tuesday evening here:
http://www.slideshare.net/mattbenic/source-andassetcontrolingamedev
The Github repo I set up for the ill-fated demo is at:
https://github.com/mattbenic/SourceControlInGameDev
The only thing really worth having in that repo is the .gitignore file, which you can use as a template when prepping your own projects for git. Other than that, those bugs are still in there waiting to be fixed, so feel free to mess around as you like to get used to git :) What I'd really love to see here is people actually trying to use this and posting any issues they run into.
Comments
Another cool thing is that tortoise git is just a ui layer that calls the command line itself, and it always shows what commands it's calling. There are several advanced git-jitsu manouveres i've pulled thanks to having a clear ui in front of me. Especially interrogating logs and viewing diffs across versions I find incredibly painful without GUI.
Unfortunately the other GUI's i've used are ...ahem... not good. And no excuse for not knowing how to use the command line at all.
I find of all the Git UI tools, it hides Git's true nature the most and people using it take the longest to click to the concepts behind Git. SourceTree and SmartGit give a far clearer idea (always showing the working set, state of all files, etc in a single view instead of having to dig through the folder hierarchy or open a separate window).
We also found TG to be pretty unstable, but to be fair it's been almost 2 years since I used it, so it may have come a long way in that time.
Found it on Gamasutra, hope it helps some folks.
So far the workflow seems to go : Make Changes -> git Add files -> git Commit -> git Push
This leads me to a few questions.
1) Do I have to explicitly call the "git add <file>" command for every file I want to commit?
2) Is it better practice to git add a file before I change it to avoid forgetting to add it later? Worst case scenario I will push a file I haven't changed.
3) Does the push command force other remote repositories to pull or does it only upload it to the bitbucket copy of the repository.
If someone can help me out that'd be cool. :)
Some tutorials to guide you through the basics of using Git or Mercurial in your workflow.
Git Tutorial: http://atlassian.com/git/
Mercurial Tutorial: http://hginit.com/
3. Push just uploads it to bitbucket (or, afaik, whatever you've set the 'origin' to be). The other repositories have to run a Pull (or Fetch) to get the changes.
2) If you add the empty file and then edit you will need to add again to update the staging area before you commit. What I do before I'm ready to commit is run git status which will show you which files have been changed, which files have been added and which files are not being tracked.
3) No, if you have to use some other mechanism to notify people of updates to the server repo. I seem to remember BitBucket does have notifications but I could be wrong
1. Make changes, test
2. Stage changes you want to commit (git add)
3. Commit (git commit)
(repeat 1-3 as needed, you can push multiple commits at a time)
4. Pull (= Fetch + Merge) (git pull)
5. Retest merged code, repeat from 1 if problems found
6. Push (git push)
Obviously now, while it's just you, you'll likely just be making changes, committing and pushing. Git won't let you push to a repository if it has newer unmerged changes anyway, it'll fail and you will need to pull and then retry. Awesome, this is exactly the sort of discussion I was hoping to see :)
1) Yes. You explicitly tell git what you want included in any given commit. git add -A will add all changed files in your working set but be sure your .gitignore is set up correctly so you don't end up committing stuff you don't need to. As jono said, this is where a GUI really comes in handy, I like to be able to quickly review the diffs per file before committing and be selective about what is committed (you can do this on commandline as well, GUI is just quicker).
2) No. When you're ready to commit (you have completed a piece of functionality, or you're at a point where you want to be able to experiment and have a safety net, etc) you add what you want to commit.
3) No. You can have your current branch (probably master right now) track a particular remote branch, and when you just git push/git pull with no additional parameters those operations will act on that remote. Your actions will have no effect on other repositories (unless there is some kind of commit hook set up on the remote, but that's a whole other kettle of fish). git remote show origin will show you which branches are tracked on that remote.
SmartGit is excellent as well though, and is a very close second choice for me. The fact that it's multiplatform and free for non commercial work is great as well :)
With it being the first truly free Git GUI of that caliber (Smart isn't really free if you're doing commercial work with it), now that it's multiplatform I wouldn't be surprised to see ST become something of a standard.
The most important thing I can say about these sort of evaluations is that it's less about which is empirically better and more about which you can be more productive in. If you've already paid the learning costs of one platform and overcome the learning curve, that is where you will inherently be more productive, and therefore will always exhibit a bias in its favour.
Disclaimer out the way, the results of my super unscientific experiment (TortoiseGit vs SourceTree)
What I like about source tree:
- The Graph looks nice, and actually makes sense. Huzzah! (the graph in tortoise is terrible)
- The UI/Button Names and such not only look nicer, but are generally a lot more consistent, consolidated and well thought out. Probably does give a better representation of the "Git way" to novices
What I don't like:- Dude, where my file tree?
- Diff viewer is meh. Linked up external diff, so probably I could learn to live with it
To expand on the negative, it feels like source tree lacks any context. Things feel a bit too automagical, which is really unnerving when things go fubar and you're trying to rescue your repo from the clutches of death. Being able to see that little tick icon overlayed on the same file structure your eyes have already seen a million times in your IDE gives me a much better sense of "what's actually happened". Though in time I guess I would get used to source trees way if I was pressed. This is actually why I don't like working on the command line - so little context!Another point is diff tools. I find that standard git/source tree representation very difficult to grok. Show me my whole god damn file. That's the way my eyes are used to seeing it in my IDE. That's definitely the way I want to see it when I'm trying to figure what the hell has gone wrong. Don't make me think more than I have to about "what function is this snippet of code actually from".
Best diff viewer in my opinion is actually the one built into monodevelop. So easy to understand exactly what's going on! And so easy to pick your changes. Wish all IDE's and Git UI's had that!
Personal preferences aside I would totally recommend it over tortoise to someone non technical.
It's worth mentioning some of the reasons I like the built in viewer:
1) It allows me to easily stage chunks of changes, something that Smart doesn't do. You can do this in commandline git, but I'd be very hesitant to do it without a view that shows me the result.
2) Image diff! I love that I can easily see previous version vs new version. This has actually helped me solve a number of real project issues.
3) Multi-file-select support. I can select all the files I've changed in a commit and get a quick overview of all changes by just scrolling down in this view. 1) Click on "Working Copy". By default this view will only show you new/modified files in a flat structure. I actually find this more useful than having to dig through the directory structure. There are definitely cases where the directories help though, so:
2) To see the files in this view laid out in a directory tree, select "Tree View" from the first dropdown above your Working Copy that is defaulted to "Flat View".
3) To change from only seeing pending (new/deleted/modified) files, select "Show All" in the second dropdown that defaults to "Show Pending".
Occurs to me SourceTree will probably handle cherry picking type operations way better that command line/tortoise-git.
And hmm... seems tree view is totally missing in the windows version. Lame.
My past versioning control experience is with SVN (also Tortoise) and Unity Asset Manager (which is of course kak).
Mercurial wins. There isn't really anything more I want out of a versioning control system. We've got five people using it (including 2 artists) and we don't have any production hindering problems. I don't care about tree view and stuff, and we recently ditched JIRA because it didn't make us more productive, so I'm not sure if the bonus features in TortoiseHG are any good.
To give Asset Server its dues, it is fantastically easy for artists to use from within Unity. It just isn't as fully featured as a modern VCS needs to be, in particular the fact that there's no branching (so no support for different released versions of your game) is a real issue.
I am trying to figure out how the branching works, but I constantly run into issues with the Temp/UnityLockfile when switching branches or trying to commit. So far as I understand it I can exclude the tracking off this file with a .gitignore file. This is the one I've been trying so far :
If I understand this correctly I'm excluding all the Library subfolders specified, any file that ends with .pidb, and the entire Temp directory. Also the file named build and the first file that ends with DS_store? But it doesn't seem to be working. The .gitignore file is placed at the root in my .git folder.
Any help or suggestions would really be appreciated.
"Temp/"
and all the Library subfolders as well. See if that does the trick?
The trick is, the .git directory isn't part of your project :) It's your repository.
Out of interest, here's a newer template .gitignore that I've been working on with @Chippit as we set up some new repos, taking experience with previous big repos into account:
https://gist.github.com/mattbenic/5300183
The problem is that all the scripts are missing from the objects. They are in the correct folders in the cloned project but they aren't linked to the objects. At first we thought it was because we forgot to enable the meta version control but that wasn't the problem.
We're using the .gitignore file that @mattbenic posted if that is any help.
Also, check that your .gitignore still matches the one on gist, I corrected something pretty major there (refined the /ProjectSettings exclusion to only exclude /ProjectSettings/EditorBuildSettings.asset)
http://gitref.org/
It's wonderfully concise (as opposed to the actual manual) with good examples and is getting me through the bulk of stuff.