<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Cocoa Is My Girlfriend &#187; Version Control</title>
	<atom:link href="http://www.cimgf.com/category/version-control/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.cimgf.com</link>
	<description>Taglines are for Windows programmers</description>
	<lastBuildDate>Thu, 15 Jul 2010 21:20:40 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Automatically save the dSYM files.</title>
		<link>http://www.cimgf.com/2009/12/23/automatically-save-the-dsym-files/</link>
		<comments>http://www.cimgf.com/2009/12/23/automatically-save-the-dsym-files/#comments</comments>
		<pubDate>Thu, 24 Dec 2009 02:28:50 +0000</pubDate>
		<dc:creator>Marcus Zarra</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Cocoa Touch]]></category>
		<category><![CDATA[Development Environment]]></category>
		<category><![CDATA[Git]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[Version Control]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[iPod Touch]]></category>

		<guid isPermaLink="false">http://www.cimgf.com/?p=843</guid>
		<description><![CDATA[For those not aware, when you compile an Objective-C application, whether it be for the desktop or for Cocoa Touch devices, the debugging symbols are stripped out of the binaries. Therefore, unlike other languages such as Java, when a crash occurs, there is virtually no way to determine where the crash occurred. However, when the [...]]]></description>
			<content:encoded><![CDATA[<p>For those not aware, when you compile an Objective-C application, whether it be for the desktop or for Cocoa Touch devices, the debugging symbols are stripped out of the binaries.  Therefore, unlike other languages such as Java, when a crash occurs, there is virtually no way to determine where the crash occurred.  However, when the applications are compiled, a dSYM bundle is generated.  This bundle allows us to match up the debugging symbols with the application&#8217;s crash log to help determine the cause of the crash.</p>

<p><span id="more-843"></span></p>

<p>The issue, however, is that the dSYM file must match the binary exactly<sup>[<a name="id394062" href="#ftn.id394062">1</a>]</sup>.  <del>I have not even had luck with pulling the code out of version control and compiling a second time to get the files to match up.</del>  Therefore, we need to store these dSYM files for every build that gets handed off to someone else.  For Cocoa Touch development this means every ad hoc build and every release build.  This can be a pain.  </p>

<p>To solve this problem I wrote a script that is added as the last build phase of all my iPhone projects.  The script will move the dSYM bundle into the project directory in a directory cleverly called &#8220;dSYM&#8221;.  In addition the script will check the bundle into git (after confirming the project is maintained in a git repository) and commit just that bundle.  Also, since the file is always named the same thing, it renames the file using the current date and time so that no two bundles have the same file name.</p>

<h2 id="failure_checks">Failure checks</h2>

<p>The first thing the script does is determine if it should run.</p>

<p><pre><code>if [ "$BUILD_STYLE" == "Debug" ]; then
  echo "Skipping debug"
  exit 0;
fi
</code></pre></p>

<p>The first part of the script checks to see if the build style is Debug.  Since all debug builds run just on the developer&#8217;s device and still contain the debug symbols, they can be safely ignored.</p>

<p><pre><code>if [ "$EFFECTIVE_PLATFORM_NAME" == "-iphonesimulator" ]; then
  echo "Skipping simulator build"
  exit 0;
fi
</code></pre></p>

<p>The second step is to check to see if the build is against the simulator.  Again, we have no interest in storing the symbol files for these builds.</p>

<h2 id="move_the_file">Move the file</h2>

<p>Since the location of the file is determined at build time and can vary from developer to developer (as well as machine to machine) I use the environmental variables that are part of the build.</p>

<p><pre><code>SRC_PATH=${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}
RELATIVE_DEST_PATH=dSYM/${EXECUTABLE_NAME}.$(date +%Y%m%d%H%M%S).app.dSYM
DEST_PATH=${PROJECT_DIR}/${RELATIVE_DEST_PATH}
echo "moving ${SRC_PATH} to ${DEST_PATH}"</p>

<p>mv "${SRC_PATH}" "${DEST_PATH}"
</code></pre></p>

<p>The next step is to build up the paths of where the file is currently and where we are going to move it to.  I like to store these in variables so that I can print them out to the console in case something goes wrong.  </p>

<h2 id="commit_it_to_version_control">Commit it to version control</h2>

<p>Every project is part of version control right? (<em>RIGHT</em>?)</p>

<p><pre><code>if [ -f ".git/config" ]; then
  git add "${RELATIVE_DEST_PATH}"
  git commit -m "Added dSYM file for ${BUILD_STYLE} build" \
      "${RELATIVE_DEST_PATH}"
fi
</code></pre></p>

<p>The final part only occurs if the project is part of a git repository.  If it is then the bundle is added to git and then just that bundle is committed with a simple message.</p>

<h2 id="conclusion">Conclusion</h2>

<p>Although I have recently been having issues getting <code>symbolicatecrash</code> to work properly, eventually either I or someone else will get it working again and at that time these files will be invaluable in tracking down crashes.</p>

<p>The final script is attached.  I normally add the file to the project and then have a script phase that just calls this script file.</p>

<p><a href="http://www.cimgf.com/wp-content/uploads/2009/12/Move_dSYM_To_Storage.sh.zip" title="Move_dSYM_To_Storage.sh.zip">Move_dSYM_To_Storage.sh.zip</a></p>

<div class="footnote"><p>
<sup>[<a name="ftn.id394062" href="#id394062">1</a>]</sup>Mach-o objects have an embedded uuid which must match the uuid of the dsym files. That&#8217;s why recompiling doesn&#8217;t work. &#8211;<a href='http://twitter.com/iamleeg/status/6998511425'>Graham Lee</a></p></div>
]]></content:encoded>
			<wfw:commentRss>http://www.cimgf.com/2009/12/23/automatically-save-the-dsym-files/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Why version control is important for solo developers</title>
		<link>http://www.cimgf.com/2009/11/07/why-version-control-is-important-for-solo-developers/</link>
		<comments>http://www.cimgf.com/2009/11/07/why-version-control-is-important-for-solo-developers/#comments</comments>
		<pubDate>Sat, 07 Nov 2009 15:22:28 +0000</pubDate>
		<dc:creator>Fraser Hess</dc:creator>
				<category><![CDATA[Git]]></category>
		<category><![CDATA[Rants]]></category>
		<category><![CDATA[Version Control]]></category>
		<category><![CDATA[microISV]]></category>

		<guid isPermaLink="false">http://www.cimgf.com/?p=786</guid>
		<description><![CDATA[It&#8217;s common practice for any software project with multiple coders to use some version control mechanism. CVS or Subversion used to be popular. These days distributed systems like git and Mercurial are the quickly replacing the old standards. But what about the cases when you&#8217;re the only coder? Let me tell you. Whatever the initial [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s common practice for any software project with multiple coders to use some version control mechanism. CVS or Subversion used to be popular. These days distributed systems like git and Mercurial are the quickly replacing the old standards. But what about the cases when you&#8217;re the only coder?
<span id="more-786"></span>
Let me tell you.  Whatever the initial setup cost, coding is much easier with version control than without it.</p>

<p>Firstly, if you think that you only work with yourself and you can handle yourself, have a quick look at the <strong>I Am A Moron</strong> section of <a href="http://www.cimgf.com/2009/03/26/dont-blindly-trust-debb/">this post</a> or <a href="http://twitter.com/kevinhoctor/status/5376014212">this recent tweet</a> by Kevin Hoctor.</p>

<p>Now a few years ago, I started work on a helpdesk ticketing system called tina. In the early days of tina development, I&#8217;d didn&#8217;t use any version control. I was frequently confused by my own code. I&#8217;d look at a piece of code and wonder, &#8220;What was I trying to do here?&#8221; or &#8220;When did I change this? Wait, did I change this?&#8221;. Occasionally, I&#8217;d tar-up my code for a historical record and I&#8217;m not sure now if I ever referred to those tarballs. When I eventually put the tina code into a Subversion repository I was much happier because of it.</p>

<p>With another project, that I wanted to put under version control, I found I had no less that 3 different versions of the code lying around on my hard drive. It look some investigation with <code>diff</code> in order to find out which one was the most current. Fortunately I didn&#8217;t have some files more recent in one copy and others more recent in another copy, but that could have easily happened.</p>

<p>With version control, it&#8217;s easy to find out what changed in my code, especially if I write useful commit messages. The most unexpected (and incredibly positive) side effect was that once I started using version control, the quality of my code went up dramatically. By tracking exactly what was changing between revisions, unwanted changes and debug code did not slip into the shipping code.</p>

<p>It&#8217;s worth noting that this approach goes hand-in-hand with unit testing.  Version control lets you know what is changing and unit testing lets you know that your changes don&#8217;t result in regressions.  As solo developers without QA teams or even a QA person, using these best practices seriously improves our ability to complete with larger organizations.</p>

<p>So, I recommend version control for any coding project bigger than a few lines of code. I used Subversion for a while and have now moved onto git.</p>

<p>My tips for version control success:</p>

<ul>
<li><strong>Make small commits</strong> &#8211; don&#8217;t commit a whole day&#8217;s work if you wrote 2 features and fixed 8 bugs. That should be at least 10 commits. For sure, commit every-time you complete something &#8211; a bugfix, a feature, fixing a typo, a formatting change. It&#8217;s makes it much easier to find regressions and other issues later. Oh, and try not to work on many things at once especially if the changes overlap in the code.
<li><strong>Compile before commit</strong> &#8211; each commit represents a known state of your code, so make sure the code compiles correctly without warnings or errors before committing.
<li><strong>Diff before commit</strong> &#8211; before each commit, look over the diff of your current code compared with the last commit.  Then you&#8217;ll know for sure what you are committing. If you don&#8217;t like part of the proposed commit, change it, diff it again, repeat until you like it and then commit.
<li><strong>Write useful messages</strong> &#8211; When you commit a message is required is usually. Make sure it makes sense to you and to others looking at your repository.
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.cimgf.com/2009/11/07/why-version-control-is-important-for-solo-developers/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>From Hacker to microISV: Tagging, Building and Releasing</title>
		<link>http://www.cimgf.com/2009/07/06/from-hacker-to-microisv-tagging-building-and-releasing/</link>
		<comments>http://www.cimgf.com/2009/07/06/from-hacker-to-microisv-tagging-building-and-releasing/#comments</comments>
		<pubDate>Mon, 06 Jul 2009 22:34:11 +0000</pubDate>
		<dc:creator>Fraser Hess</dc:creator>
				<category><![CDATA[Git]]></category>
		<category><![CDATA[Version Control]]></category>
		<category><![CDATA[microISV]]></category>

		<guid isPermaLink="false">http://www.cimgf.com/?p=671</guid>
		<description><![CDATA[It is important to develop a consistent build process for your applications. I have written a couple of bash scripts to help me with this process. I use git for version control and also the services of github. Now in another post on this site Marcus covered how to put git commit checksums in your [...]]]></description>
			<content:encoded><![CDATA[<p>It is important to develop a consistent build process for your applications.  I have written a couple of bash scripts to help me with this process.</p>

<p>I use git for version control and also the services of <a href="http://github.com">github</a>.  Now in <a href="http://www.cimgf.com/2008/04/13/git-and-xcode-a-git-build-number-script/">another post</a> on this site Marcus covered how to put git commit checksums in your Info.plist&#8217;s CFBundleVersion.  I have opted to use Apple Generic Versioning (or agv for short) instead as it has an easy to read incrementing build number and is super  easy to script. It&#8217;s also great for use with Sparkle since Sparkle uses the CFBundleVersion to see if the appcast has a newer version.
<span id="more-671"></span>
Chris Hanson wrote a <a href="http://chanson.livejournal.com/125568.html">great piece</a> a few years back about getting agv setup in your XCode project.  I followed his instructions for that.  I also set the <strong>CFBundleShortVersionString</strong> in Info.plist to <strong>__VERSION__</strong>.  You&#8217;ll see why I do that later.</p>

<p>When it comes time to build my app for shipping, either privately or publicly, I run <code>tag.sh</code>.  This bash script increments the agv version and creates a git tag.  The script takes one parameter which is the marketing version of your build (1.0, 2.0.4fc1, 2.5b6 etc).</p>

<p>Before running <code>tag.sh</code>, the state of the git repo should be clean- there should be no other staged files or uncommitted edits.  It&#8217;s also a good idea to close the XCode project since <code>agvtool</code> will modify the XCode project file.</p>

<p><code>tag.sh</code> also takes care of committing the changed CFBundleVersion for you.  Here is it&#8217;s code:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/sh</span>
<span style="color: #007800;">tag</span>=$<span style="color: #000000;">1</span>
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$tag</span>&quot;</span> == <span style="color: #ff0000;">&quot;&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span>
	<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;No tag specified&quot;</span>
	<span style="color: #7a0874; font-weight: bold;">exit</span>
<span style="color: #000000; font-weight: bold;">fi</span>
agvtool next-version <span style="color: #660033;">-all</span>
git commit <span style="color: #660033;">-a</span> <span style="color: #660033;">-m</span> <span style="color: #ff0000;">&quot;Increment CFBundleVersion for <span style="color: #007800;">$tag</span>&quot;</span>
git tag <span style="color: #660033;">-m</span> <span style="color: #ff0000;">&quot;Tag for <span style="color: #007800;">$tag</span>&quot;</span> <span style="color: #660033;">-a</span> <span style="color: #007800;">$tag</span>
git push origin master
git push <span style="color: #660033;">--tags</span></pre></td></tr></table></div>


<p>So having run <code>tag.sh</code> I have created a git tag for my build so I can always go back and see that version of the code either in github or using <code>git checkout &lt;tag name&gt;</code> at the command line.</p>

<p>After this I use a jumbo script that checks out the tag I just created, builds it, zips it up, uploads it to my web server, outputs an <code>&lt;item&gt;</code> for your Sparkle Appcast (including signing the update) and maybe tweets about it. Phew. It&#8217;s a heavily modified version of <a href="http://code.google.com/p/flycode/source/browse/trunk/buildapp/bin/babuild.sh">Gus Mueller&#8217;s build script</a>.  Here&#8217;s the usage:</p>

<p><code>build.sh -p ProjectName -t tag [-u [-w tweet]]</code></p>

<p>The two required parameters are a project name and a tag.  Optionally you can upload and then tweet about the newly available build.  I do all of my public builds in a separate clone of my git repo that never gets edited or otherwise messed with (~/Development/building/).  There&#8217;s a whole lot going on in this script that could be explained, but for now I&#8217;ll just leave you with the code to walk through, and if something needs clarified, post a comment and I&#8217;ll do my best.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
</pre></td><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/bash</span>
&nbsp;
<span style="color: #007800;">upload</span>=<span style="color: #000000;">0</span>
<span style="color: #007800;">tweet</span>=<span style="color: #ff0000;">&quot;&quot;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">while</span> <span style="color: #7a0874; font-weight: bold;">getopts</span> <span style="color: #ff0000;">&quot;:t:up:w:&quot;</span> Option
<span style="color: #000000; font-weight: bold;">do</span>
  <span style="color: #000000; font-weight: bold;">case</span> <span style="color: #007800;">$Option</span> <span style="color: #000000; font-weight: bold;">in</span>
    <span style="color: #c20cb9; font-weight: bold;">w</span> <span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #007800;">tweet</span>=<span style="color: #007800;">$OPTARG</span><span style="color: #000000; font-weight: bold;">;;</span>
    u <span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #007800;">upload</span>=<span style="color: #000000;">1</span><span style="color: #000000; font-weight: bold;">;;</span>
    p <span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #007800;">project</span>=<span style="color: #007800;">$OPTARG</span><span style="color: #000000; font-weight: bold;">;;</span>
    t <span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #007800;">tag</span>=<span style="color: #007800;">$OPTARG</span><span style="color: #000000; font-weight: bold;">;;</span>
  <span style="color: #000000; font-weight: bold;">esac</span>
<span style="color: #000000; font-weight: bold;">done</span>
<span style="color: #7a0874; font-weight: bold;">shift</span> $<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #007800;">$OPTIND</span> - <span style="color: #000000;">1</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$project</span>&quot;</span> == <span style="color: #ff0000;">&quot;&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span>
	<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;No project specified&quot;</span>
	<span style="color: #7a0874; font-weight: bold;">exit</span>
<span style="color: #000000; font-weight: bold;">fi</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$tag</span>&quot;</span> == <span style="color: #ff0000;">&quot;&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span>
	<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;No tag specified&quot;</span>
	<span style="color: #7a0874; font-weight: bold;">exit</span>
<span style="color: #000000; font-weight: bold;">fi</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># Configuration</span>
<span style="color: #007800;">final_builds</span>=~<span style="color: #000000; font-weight: bold;">/</span>Development<span style="color: #000000; font-weight: bold;">/</span>release_builds
<span style="color: #007800;">code_folder</span>=~<span style="color: #000000; font-weight: bold;">/</span>Development<span style="color: #000000; font-weight: bold;">/</span>building<span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">$project</span>
<span style="color: #007800;">build_folder</span>=<span style="color: #007800;">$code_folder</span><span style="color: #000000; font-weight: bold;">/</span>build
<span style="color: #007800;">keys_folder</span>=~<span style="color: #000000; font-weight: bold;">/</span>Development<span style="color: #000000; font-weight: bold;">/</span>keys
<span style="color: #007800;">upload_destination</span>=user<span style="color: #000000; font-weight: bold;">@</span>yourcompany.com:<span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>apache2<span style="color: #000000; font-weight: bold;">/</span>htdocs<span style="color: #000000; font-weight: bold;">/</span>downloads<span style="color: #000000; font-weight: bold;">/</span>
<span style="color: #007800;">release_notes_webfolder</span>=http:<span style="color: #000000; font-weight: bold;">//</span>yourcompany.com<span style="color: #000000; font-weight: bold;">/</span>releasenotes
<span style="color: #007800;">downloads_webfolder</span>=http:<span style="color: #000000; font-weight: bold;">//</span>yourcompany.com<span style="color: #000000; font-weight: bold;">/</span>downloads
<span style="color: #007800;">twitter_uname</span>=someone<span style="color: #000000; font-weight: bold;">@</span>somewhere.com
<span style="color: #007800;">twitter_pword</span>=password
&nbsp;
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #000000; font-weight: bold;">!</span> <span style="color: #660033;">-d</span>  <span style="color: #007800;">$final_builds</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span>
	<span style="color: #c20cb9; font-weight: bold;">mkdir</span> <span style="color: #007800;">$final_builds</span>
<span style="color: #000000; font-weight: bold;">fi</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># clean up</span>
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-d</span> <span style="color: #007800;">$build_folder</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span>
	<span style="color: #c20cb9; font-weight: bold;">rm</span> <span style="color: #660033;">-rf</span> <span style="color: #007800;">$build_folder</span>
<span style="color: #000000; font-weight: bold;">fi</span>
&nbsp;
<span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #007800;">$code_folder</span>
&nbsp;
git pull origin master
git pull <span style="color: #660033;">--tags</span>
git checkout <span style="color: #007800;">$tag</span>
&nbsp;
<span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-i</span> <span style="color: #ff0000;">&quot;&quot;</span> <span style="color: #ff0000;">'s/__VERSION__/'</span><span style="color: #007800;">$tag</span><span style="color: #ff0000;">'/g'</span> Info.plist
&nbsp;
<span style="color: #7a0874; font-weight: bold;">echo</span> building project
xcodebuild <span style="color: #660033;">-target</span> <span style="color: #007800;">$project</span> <span style="color: #660033;">-configuration</span> Release <span style="color: #007800;">OBJROOT</span>=<span style="color: #007800;">$build_folder</span> <span style="color: #007800;">SYMROOT</span>=<span style="color: #007800;">$build_folder</span> <span style="color: #007800;">OTHER_CFLAGS</span>=<span style="color: #ff0000;">&quot;&quot;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #007800;">$?</span> <span style="color: #000000; font-weight: bold;">!</span>= <span style="color: #000000;">0</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span>
	<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Bad build for <span style="color: #007800;">$project</span>&quot;</span>
	say <span style="color: #ff0000;">&quot;bad build!&quot;</span>
<span style="color: #000000; font-weight: bold;">else</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">#ok, let's index the documentation if we've got it.</span>
	<span style="color: #666666; font-style: italic;">#/Developer/Applications/Utilities/Help\ Indexer.app/Contents/MacOS/Help\ Indexer &quot;/tmp/buildapp/build/Release/BuildApp.app/Contents/Resources/English.lproj/BuildAppHelp&quot;</span>
&nbsp;
	<span style="color: #c20cb9; font-weight: bold;">mv</span> <span style="color: #007800;">$build_folder</span><span style="color: #000000; font-weight: bold;">/</span>Release<span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">$project</span>.app <span style="color: #007800;">$final_builds</span>
&nbsp;
	<span style="color: #666666; font-style: italic;"># make the zip file</span>
	<span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #007800;">$final_builds</span>
	<span style="color: #c20cb9; font-weight: bold;">zip</span> <span style="color: #660033;">-r</span> <span style="color: #007800;">$project</span>-<span style="color: #007800;">$tag</span>.zip <span style="color: #007800;">$project</span>.app
&nbsp;
	<span style="color: #c20cb9; font-weight: bold;">rm</span> <span style="color: #660033;">-rf</span> <span style="color: #007800;">$project</span>.app
&nbsp;
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #007800;">$upload</span> == <span style="color: #000000;">1</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span>
&nbsp;
		<span style="color: #7a0874; font-weight: bold;">echo</span> uploading to server...
		<span style="color: #666666; font-style: italic;"># upload</span>
		<span style="color: #c20cb9; font-weight: bold;">scp</span> <span style="color: #007800;">$project</span>-<span style="color: #007800;">$tag</span>.zip <span style="color: #007800;">$upload_destination</span>
&nbsp;
		<span style="color: #666666; font-style: italic;"># get values for appcast</span>
		<span style="color: #007800;">dsasignature</span>=<span style="color: #000000; font-weight: bold;">`</span><span style="color: #007800;">$keys_folder</span><span style="color: #000000; font-weight: bold;">/</span>sign_update.rb <span style="color: #007800;">$final_builds</span><span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">$project</span>-<span style="color: #007800;">$tag</span>.zip <span style="color: #007800;">$keys_folder</span><span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">$project</span>\_dsa_priv.pem<span style="color: #000000; font-weight: bold;">`</span>
		<span style="color: #007800;">filesize</span>=<span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">stat</span> <span style="color: #660033;">-f</span> <span style="color: #000000; font-weight: bold;">%</span>z <span style="color: #007800;">$final_builds</span><span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">$project</span>-<span style="color: #007800;">$tag</span>.zip<span style="color: #000000; font-weight: bold;">`</span>
		<span style="color: #007800;">pubdate</span>=<span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">date</span> <span style="color: #ff0000;">&quot;+%a, %d %h %Y %T %z&quot;</span><span style="color: #000000; font-weight: bold;">`</span>
&nbsp;
		<span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #007800;">$code_folder</span>
&nbsp;
		<span style="color: #007800;">cfbundleversion</span>=<span style="color: #000000; font-weight: bold;">`</span>agvtool what-version -terse<span style="color: #000000; font-weight: bold;">`</span>
&nbsp;
		<span style="color: #666666; font-style: italic;">#output appcast item</span>
		<span style="color: #7a0874; font-weight: bold;">echo</span>
		<span style="color: #7a0874; font-weight: bold;">echo</span> Put the following text <span style="color: #000000; font-weight: bold;">in</span> your appcast
		<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;&lt;item&gt;&quot;</span>
		<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;&lt;title&gt;Version <span style="color: #007800;">$tag</span>&lt;/title&gt;&quot;</span>
		<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;&lt;sparkle:releaseNotesLink&gt;&quot;</span>
		<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$release_notes_webfolder</span>/<span style="color: #007800;">$project</span>.html&quot;</span>
		<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;&lt;/sparkle:releaseNotesLink&gt;&quot;</span>
		<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;&lt;pubDate&gt;<span style="color: #007800;">$pubdate</span>&lt;/pubDate&gt;&quot;</span>
		<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;&lt;enclosure url=<span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #007800;">$downloads_webfolder</span>/<span style="color: #007800;">$project</span>-<span style="color: #007800;">$tag</span>.zip<span style="color: #000099; font-weight: bold;">\&quot;</span>&quot;</span>
		<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;sparkle:version=<span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #007800;">$cfbundleversion</span><span style="color: #000099; font-weight: bold;">\&quot;</span>&quot;</span>
		<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;sparkle:shortVersionString=<span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #007800;">$tag</span><span style="color: #000099; font-weight: bold;">\&quot;</span>&quot;</span>
		<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;sparkle:dsaSignature=<span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #007800;">$dsasignature</span><span style="color: #000099; font-weight: bold;">\&quot;</span>&quot;</span>
		<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;length=<span style="color: #000099; font-weight: bold;">\&quot;</span><span style="color: #007800;">$filesize</span><span style="color: #000099; font-weight: bold;">\&quot;</span>&quot;</span>
		<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;type=<span style="color: #000099; font-weight: bold;">\&quot;</span>application/octet-stream<span style="color: #000099; font-weight: bold;">\&quot;</span> /&gt;&quot;</span>
		<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;&lt;/item&gt;&quot;</span>
		<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$tweet</span>&quot;</span> <span style="color: #000000; font-weight: bold;">!</span>= <span style="color: #ff0000;">&quot;&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span>
			<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Calling twitter: <span style="color: #007800;">$tweet</span>&quot;</span>
			curl <span style="color: #660033;">-u</span> <span style="color: #007800;">$twitter_uname</span>:<span style="color: #007800;">$twitter_pword</span> <span style="color: #660033;">-d</span> <span style="color: #007800;">status</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$project</span> <span style="color: #007800;">$tag</span> is up. <span style="color: #007800;">$tweet</span>&quot;</span> http:<span style="color: #000000; font-weight: bold;">//</span>twitter.com<span style="color: #000000; font-weight: bold;">/</span>statuses<span style="color: #000000; font-weight: bold;">/</span>update.xml
		<span style="color: #000000; font-weight: bold;">fi</span>
	<span style="color: #000000; font-weight: bold;">fi</span>
&nbsp;
	open <span style="color: #007800;">$final_builds</span>
	say <span style="color: #ff0000;">&quot;done building&quot;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">fi</span>
&nbsp;
<span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #007800;">$code_folder</span>
git checkout Info.plist
<span style="color: #c20cb9; font-weight: bold;">rm</span> <span style="color: #660033;">-rf</span> <span style="color: #007800;">$build_folder</span></pre></td></tr></table></div>


<p><b>Other References</b></p>

<p><a href="http://github.com/guides/push-tags-to-github">Push tags to github</a>
<a href="http://sparkle.andymatuschak.org/documentation/pmwiki.php/Documentation/BasicSetup">Sparkle Basic Setup</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.cimgf.com/2009/07/06/from-hacker-to-microisv-tagging-building-and-releasing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Version Control Makes You A Better Programmer</title>
		<link>http://www.cimgf.com/2008/06/03/version-control-makes-you-a-better-programmer/</link>
		<comments>http://www.cimgf.com/2008/06/03/version-control-makes-you-a-better-programmer/#comments</comments>
		<pubDate>Tue, 03 Jun 2008 17:47:45 +0000</pubDate>
		<dc:creator>Matt Long</dc:creator>
				<category><![CDATA[Advanced]]></category>
		<category><![CDATA[Coding Practice]]></category>
		<category><![CDATA[Development Environment]]></category>
		<category><![CDATA[Git]]></category>
		<category><![CDATA[Version Control]]></category>

		<guid isPermaLink="false">http://www.cimgf.com/?p=130</guid>
		<description><![CDATA[I&#8217;m a believer. I&#8217;ve used version control before, but Marcus has convinced me that with a little known version control system called Git, written by Linus Torvalds (the creator of Linux), version control is not just about versioning, it&#8217;s about expressing yourself with your code and collaborating with others, seamlessly. As memory serves the only [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m a believer. I&#8217;ve used version control before, but Marcus has convinced me that with a little known version control system called <a href="http://www.kernel.org/pub/software/scm/git/docs/tutorial.html">Git</a>, written by <a href="http://en.wikipedia.org/wiki/Linus_Torvalds">Linus Torvalds</a> (the creator of Linux), version control is not just about versioning, it&#8217;s about expressing yourself with your code and collaborating with others, seamlessly.</p>

<p>As memory serves the only time I&#8217;ve used version control in a meaningful way the system I was using was Visual SourceSafe from Microsoft. I know. Blech! It&#8217;s awful! I&#8217;ve <em>pulled</em> code from many a CVS or Subversion repository, but I&#8217;ve never really used them in the way they are intended to be used. Now, thanks to Marcus, I realize that version control isn&#8217;t just about versioning any more. It&#8217;s a whole methodology/ideology that makes better programmers. Here is what I mean.
<span id="more-130"></span></p>

<h2>Branching Inspires Wild Experimentation</h2>

<p>Have you ever been so far down a path in your code that you just think, though you probably should, there is no way you would take a chance to re-factor due to looming deadlines or even just a simple fear that you might mess up so badly you couldn&#8217;t recover? Well, fear no more! Git provides such a simple way to create a branch of your code in which you can experiment, you won&#8217;t even give it a second thought. I won&#8217;t go into the whole setup and how to get going with Git as this is done very well elsewhere <a href="http://www.cimgf.com/2008/03/18/git-and-mac-a-match-made-in-purgatory/">including a previous post from Marcus</a>. I just want to point out how easy it is to branch with a single command. In Terminal.app, <em>cd</em> to the directory of a project you have under Git source control and enter the following command.
<pre>
bash$ git branch experimental
</pre>
That&#8217;s all there is to it. You now have a nice shiny clean slate to experiment with abandon. You simply type:
<pre>
bash$ git checkout experimental
</pre>
and you are now working on the <em>experimental</em> branch you just created. Now you can just run amok and have nothing to worry about. Make crazy experimental changes to your heart&#8217;s content and all you need to do to go back to your original code base is type:
<pre>
bash$ git checkout master
</pre>
and you&#8217;re back in business. If you found that your crazy coding excursion was a great success, you can merge your changes in with the following commands.
<pre>
bash$ git checkout master
bash$ git merge experimental
</pre>
The first command switches you back to the <em>master</em> branch, while the second performs the merge of the code from the <em>experimental</em> branch into the <em>master</em> branch. If there are conflicts, you will have to fix them manually, but it seems that the need to do so is pretty rare. Git does a great job at merging changes automatically.</p>

<p>If you found, conversely, that your ideas were purely delusional&#8211;a characteristic of your over-achieving sense of hubris&#8211;you can blow them away by simply typing:
<pre>
bash$ git branch -d experimental
</pre></p>

<p>Now the idea is just a bad memory and not something you ever need worry about (or mention to your programming peers) again. Your code on the master branch is still as it was when you first started the branch. Hallelujah!</p>

<blockquote><strong>Note:</strong> The word &#8216;experimental&#8217; I&#8217;ve used in these command line examples is simply a tag. You can call your branch whatever you like. Call it &#8216;hubris&#8217; if you like. Depending on your personality, this may be more appropriate.</blockquote>

<p>The chance to experiment so easily and without fear will make you a better programmer. You will venture into areas that you would have never tried before and will likely become more bold in what you&#8217;re willing to attempt. This can only be a good thing in the long run.</p>

<h2>Collaboration</h2>

<p>The <a href="http://www.kernel.org/pub/software/scm/git/docs/tutorial.html">Tutorial introduction to git</a> provides a good example of how to collaborate when multiple people are working on the same computer, but where Git&#8217;s real power comes in is in its ability to enable collaboration. If you&#8217;re familiar with extreme programming or pair programming then you are already aware of how collaboration will make you a better programmer. The learning curve for developing applications for the Macintosh for me has been significantly leveled as Marcus has shown me how to do things in the context of real code. You can learn things in many different ways, but sharing code has got to be one of the strongest means of gaining deeper understanding. This can only make you a better programmer.</p>

<p>While not a direct feature of Git itself, you can share your repository over the many file sharing web applications out there. Marcus and I use <a href="http://www.getdropbox.com/">Dropbox</a> for our projects that we collaborate on. Here are the steps you take to collaborate remotely using Git and Dropbox.</p>

<ol>
<li>Sign up and install Dropbox from <a href="http://www.getdropbox.com/">http://www.getdropbox.com</a>.<br />
<br />This will create a folder in your home directory under <em>~/Dropbox</em>.</li>

<li>Have the person you want to collaborate with do the same and then create a shared folder that both of you can access through the Dropbox web interface.<br /><br /></li>

<li>From the project directory of the project you want to share, type:
<pre>
bash$ git clone --bare . ~/Dropbox/Shared/MySharedProject.git
</pre>
<blockquote>
<strong>Note:</strong> Keep in mind that I&#8217;m assuming you already have this project under Git version control. If not you first need to run init like so in the root of your project directory.
<pre>
bash$ git init
</pre>
</blockquote>

The <strong>&#8211;bare</strong> keyword we used in the clone command means that we simply want to create a directory that contains the contents of the .git directory in your project directory and not the actual workspace. The .git directory contains all of your code and changes to everything you need is there&#8211;it&#8217;s just not the actual workspace where xcode works from. 

</li>
<li>Create a remote (alias) for the newly cloned project by typing:
<pre>
bash$ git remote add sharedproject ~/Dropbox/Shared/MySharedProject.git
</pre>
</li><br />
<li>Now you can push any code changes from your working directory to the cloned directory, which, since it is in your <em>Dropbox</em> will automatically be uploaded to the drop box and downloaded by any other computers you have that can access <em>Dropbox</em>. First you need to commit any changes in your working directory with the following command.
<pre>
bash$ git commit -a -m "Commit message"
</pre>
Then you need to push the changes to the remote with the following.
<pre>
bash$ git push sharedproject master
</pre>
This pushes your changes to the cloned repository which is in your </em>Dropbox</em> directory. As soon as you do this, you should see the <em>Dropbox</em> icon in your menu bar change to the &#8216;synchronizing&#8217; icon. If your change is small, it will only change for a split second so you&#8217;ll have to watch it closely to see that happen.
</li>
</ol>

<p>Once your files are committed and have been pushed to your cloned repository, you can now <em>pull</em> the project from another computer. I&#8217;m assuming you have <em>Git</em> and <em>Dropbox</em> set up on the second computer. Here are the steps you take to get the code into Git.</p>

<ol>
<li>In Terminal.app on your other computer, create a new directory where you want your project to be stored with a working directory. Now run the following command.
<pre>
bash$ git clone ~/Dropbox/Shared/MySharedProject.git
</pre>
Notice that we didn&#8217;t use the <strong>&#8211;bare</strong> keyword this time. This is because we want our cloned copy to also setup a working directory since we&#8217;ll be accessing it from xcode on the second computer as well.
</li>
<li>Now create a remote (alias) to reference the project like you did on the other computer using the following.
<pre>
bash$ git remote add sharedproject ~/Dropbox/Shared/MySharedProject.git
</pre>
<blockquote><strong>Note:</strong> This step is optional as your clone will do this automatically. The difference, however, is that the clone will create a remote called &#8216;origin&#8217; by default where you can name it whatever you want (sharedproject in the example) if you do run it.</blockquote>
</li>
<li>Now you can pull the code at any time with the following command.
<pre>
bash$ git pull sharedproject master
</pre>
You won&#8217;t need to do that at this point as your code is fresh from the clone, however, should you make any changes on the originating computer that have been pushed, you could now pull those changes from this secondary computer.
</ul>
</ol>

<p>If you now make changes to the code on the second computer, you can use the exact same command you used on the first computer to push the changes. First commit the changes with:
<pre>
bash$ git commit -a -m "Commit message"
</pre>
Then simply push the changes to the cloned repository with:
<pre>
bash$ git push sharedproject master
</pre></p>

<p>And now you&#8217;re up to date. The changes are ready to be downloaded from the first computer.</p>

<h2>The Urge To Merge</h2>

<p>Nothing like sexual inuendo (urge to merge, hint hint, wink wink) on a site called &#8216;Cocoa is my Girlfriend&#8217; to get a geek going, but that&#8217;s not what I mean. Settle down. Take it easy&#8230;</p>

<p>In the end, Git&#8217;s greatest feature is its ability to merge code changes.</p>

<p>There are times when you have fairly complex code merges that are necessary and systems such as CVS or SVN (Subversion) will simply choke and give up leaving the messy merging process to your weak manual merging skills. This is a shame and not necessary any more as it is rare for Git to be unable to successfully merge code. Again, this probably its biggest strength. When you don&#8217;t have to worry about merging your code, you can do whatever you like in your branch with little fear that merging in your changes are going to conflict with someone else&#8217;s. This merging power comes from Git&#8217;s unique philosophy of source code management which sees changes as individual code additions and deletions rather than complete file changes.</p>

<h2>Conclusion</h2>

<p>There will remain naysayers who have &#8220;always done it this way&#8221; and will remain in the realm of central repositories for version control. However, if you can think outside of tradition and see the power that comes from a good source control system, you will become a better programmer. I will submit that simply starting to use any version control when you haven&#8217;t before will make you a better programmer, however, using Git for your version control system, will make it infinitely easier to become so.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cimgf.com/2008/06/03/version-control-makes-you-a-better-programmer/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Git and XCode: A git build number script</title>
		<link>http://www.cimgf.com/2008/04/13/git-and-xcode-a-git-build-number-script/</link>
		<comments>http://www.cimgf.com/2008/04/13/git-and-xcode-a-git-build-number-script/#comments</comments>
		<pubDate>Mon, 14 Apr 2008 01:36:48 +0000</pubDate>
		<dc:creator>Marcus Zarra</dc:creator>
				<category><![CDATA[Coding Practice]]></category>
		<category><![CDATA[Development Environment]]></category>
		<category><![CDATA[Git]]></category>
		<category><![CDATA[Version Control]]></category>

		<guid isPermaLink="false">http://www.cimgf.com/?p=95</guid>
		<description><![CDATA[Git has been gaining in popularity with Cocoa developers as well as open source developers. As I work it into my development workflow, one item that was missing was the automatic injection of the build number into the application bundle. There are a few scripts floating around that perform this trick for subversion, but git [...]]]></description>
			<content:encoded><![CDATA[<p>Git has been gaining in popularity with Cocoa developers as well as open source developers.  As I work it into my development workflow, one item that was missing was the automatic injection of the build number into the application bundle.</p>

<p>There are a few scripts floating around that perform this trick for subversion, but git handles build numbers a bit differently and it appears that no one has bothered to publish one.  As is known, subversion uses an incrementing integer for build numbers.  This makes it very easy to determine which build number came first and makes it very useful for a non-public version number.  Git, however, uses a hash for each build number which is not incrementing and therefore not very useful for determining version numbers.  However, it is still very useful for pulling up a specific build when a crash report is received, etc.</p>

<p>Therefore, with the help of Matt Long&#8217;s perl-fu, I have updated Daniel Jalkut&#8217;s subversion perl script to work with git.  Since the build numbers are not sequential, I would not recommend using them for Sparkle.  Therefore, in my own build process for iWeb Buddy, I hand select the version number (for example 1.0.4) and then use the short hash from git as the CFBundleVersion number.  Normally this number is displayed in parens after the primary build number but, at least in iWeb Buddy, I have removed it from the display entirely.  Since it is no longer a sequential number it would only potentially confuse users and it displays in the crash reports anyway.</p>

<p>The updated script is as follows:</p>


<div class="wp_syntax"><div class="code"><pre class="perl" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># Xcode auto-versioning script for Subversion by Axel Andersson</span>
<span style="color: #666666; font-style: italic;"># Updated for git by Marcus S. Zarra and Matt Long</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">use</span> strict<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># Get the current git commit hash and use it to set the CFBundleVersion value</span>
<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$REV</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">`/opt/local/bin/git show --abbrev-commit | grep &quot;^commit&quot;`</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$INFO</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;$ENV{BUILT_PRODUCTS_DIR}/$ENV{WRAPPER_NAME}/Contents/Info.plist&quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$version</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$REV</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">$version</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">/^commit\s+([^.]+)\.\.\.$/</span> <span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span> 
	<span style="color: #0000ff;">$version</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$1</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #b1b100;">else</span>
<span style="color: #009900;">&#123;</span>
	<span style="color: #0000ff;">$version</span> <span style="color: #339933;">=</span> <span style="color: #000066;">undef</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #000066;">die</span> <span style="color: #ff0000;">&quot;$0: No Git revision found&quot;</span> <span style="color: #b1b100;">unless</span> <span style="color: #0000ff;">$version</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000066;">open</span><span style="color: #009900;">&#40;</span>FH<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;$INFO&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">or</span> <span style="color: #000066;">die</span> <span style="color: #ff0000;">&quot;$0: $INFO: $!&quot;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$info</span> <span style="color: #339933;">=</span> <span style="color: #000066;">join</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;&quot;</span><span style="color: #339933;">,</span> <span style="color: #009999;">&lt;FH&gt;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000066;">close</span><span style="color: #009900;">&#40;</span>FH<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #0000ff;">$info</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">s/([\t ]+&lt;key&gt;CFBundleVersion&lt;\/key&gt;\n[\t ]+&lt;string&gt;).*?(&lt;\/string&gt;)/$1$version$2/</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000066;">open</span><span style="color: #009900;">&#40;</span>FH<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;&gt;$INFO&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">or</span> <span style="color: #000066;">die</span> <span style="color: #ff0000;">&quot;$0: $INFO: $!&quot;</span><span style="color: #339933;">;</span>
<span style="color: #000066;">print</span> FH <span style="color: #0000ff;">$info</span><span style="color: #339933;">;</span>
<span style="color: #000066;">close</span><span style="color: #009900;">&#40;</span>FH<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>


<p>Since git is distributed, there is no need to be online to produce a build.  The script will grab the current abbrev-commit hash and will inject it into the current build&#8217;s Info.plist file.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cimgf.com/2008/04/13/git-and-xcode-a-git-build-number-script/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Git and .mac: A Match Made In Purgatory</title>
		<link>http://www.cimgf.com/2008/03/18/git-and-mac-a-match-made-in-purgatory/</link>
		<comments>http://www.cimgf.com/2008/03/18/git-and-mac-a-match-made-in-purgatory/#comments</comments>
		<pubDate>Tue, 18 Mar 2008 20:16:06 +0000</pubDate>
		<dc:creator>Marcus Zarra</dc:creator>
				<category><![CDATA[Development Environment]]></category>
		<category><![CDATA[Git]]></category>
		<category><![CDATA[Version Control]]></category>

		<guid isPermaLink="false">http://www.cimgf.com/2008/03/18/git-and-mac-a-match-made-in-purgatory/</guid>
		<description><![CDATA[Last year, I made the switch from subversion to Git. After 9+ months of using Git, I can comfortably say that it was a very good choice. While branching is easy in subversion, merging is just as bad as it was in cvs. Git is a significant improvement over that. In addition, since Git is [...]]]></description>
			<content:encoded><![CDATA[<p>Last year, I made the switch from subversion to <a href="http://git.or.cz/">Git</a>.  After 9+ months of using Git, I can comfortably say that it was a very good choice.  While branching is easy in subversion, merging is just as bad as it was in cvs.  Git is a significant improvement over that.  In addition, since Git is a true distributed source control system, I can easily do branches and merges on my local machine without an internet connection and just &#8220;push&#8221; my changes to my off-site server when it is convenient.</p>

<p>I am also a user of .mac.  I like the service and the iDisk is probably my favorite feature.  Therefore, I wondered, like chocolate and peanut butter, could I put these two together and come up with something better than the individual parts?
<span id="more-66"></span></p>

<p>The answer is yes.  They work amazingly well together and make it very easy for me to push my code changes off-site even when I am not actually connected to the net.  The basic configuration is fairly simple.  I created a private directory on .mac, set up a bare repository in that directory and defined that directory as a remote location for my Git workspace.  Below are the details on how to accomplish this.</p>

<h2>Install Git on OS X</h2>

<p>First, you need to have Git.  The easiest way that I have found to get it is to use the <a href='http://www.macports.org'>MacPorts</a> and do a &#8216;sudo port install git-core +svn&#8217;.  I add svn because once you get used to Git you will want to put it in front of all your svn repositories that all those stone age developers still use.</p>

<blockquote><strong>Note:</strong> After installing MacPorts, you may need to add /opt/local/bin to your PATH in order for the <em>port</em> command to be found from the command line. Edit your .bash_profile file in your home directory (assuming you use bash) in Terminal and add the following line to the bottom of the file: <strong>export PATH=/opt/local/bin:$PATH
</strong>.</blockquote>

<h2>Create your working repository</h2>

<p>Once you have Git installed, you will want to create a repository.  That is accomplished with a single call:</p>

<p><pre>
mkdir TempProject
cd TempProject
git init
</pre></p>

<p>What that does is create a single directory called .git in the TempProject directory.  All of the version information for that workspace is stored in that single .git directory (hello Subversion guys, your .svn directories suck).</p>

<h2>Set up the bare clone</h2>

<p>Now that your repository is created, you want to create a remote copy of it in case your harddrive eats itself or gets stolen (BTW Wil, <a href="http://wilshipley.com/blog/2008/02/ted2008-part-1-gossip.html">sorry to hear about your MBA</a>, that thief should burn).  To do that, you want to have iDisk local syncing turned on.  When it is, you will have a directory under /Volumes with your .mac username.  For instance, mine is at /Volumes/mzarra.  In this directory you want to create a new directory (I called mine git).  Make sure that directory can only be accessed by you.</p>

<p>Now that it is created, you want to build the bare clone of your workspace.  To accomplish this, execute the following:</p>

<p><pre>
cd TempProject
git clone --bare . /Volumes/${USERNAME}/git/TempProject.git
</pre></p>

<p>After a few moments your new bare clone is ready.</p>

<h2>Linking the remote clone</h2>

<p>The final step is to tell your local repository where that remote repository is:</p>

<p><pre>
cd TempProject
git remote add origin /Volumes/${USERNAME}/git/TempProject.git
</pre></p>

<p>Note that I used origin as this is the default repository name for push and pull.  If you want your origin to be somewhere else then change this name.</p>

<h2>Performing a push</h2>

<p>Now that everything is set up all you need to do to sync your repositories is:</p>

<p><pre>
git push
</pre></p>

<p>And Git will update the bare clone.</p>

<h2>Sync multiple working copies</h2>

<p>But wait &#8212; there is more.  If you have more than one Mac, you can use this bare clone to keep your two workspaces in sync!  On the other Mac, once Git is installed, you can grab a working copy as follows:</p>

<p><pre>
git clone /Volumes/${USERNAME}/git/TempProject.git
</pre></p>

<p>And you will now have another working copy!  If you need to update your second Mac at a later point just:</p>

<p><pre>
git pull
</pre></p>

<p>And Git will do all the work for you.</p>

<h2>Conclusion</h2>

<p>There are a couple things to note.</p>

<ul>
<li>The initial sync back to .mac can be slow if your workspace is large.  However, as long as you &#8216;push&#8217; often enough, your subsequent syncs should be very quick.  Therefore, get in the habit of pushing often.</li>
<br />
<li> Only one Mac can sync with .mac at a time.  Therefore it is possible to get a sync failure if the n Macs try to sync at the same time.  Therefore if you are going to do a pull and you <em>just</em> pushed to .mac, make sure that both syncs succeeded.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.cimgf.com/2008/03/18/git-and-mac-a-match-made-in-purgatory/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>
