<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Git on blog.iankulin.com</title><link>https://blog.iankulin.com/tags/git/</link><description>Recent content in Git on blog.iankulin.com</description><generator>Hugo</generator><language>en-AU</language><lastBuildDate>Fri, 15 Dec 2023 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.iankulin.com/tags/git/index.xml" rel="self" type="application/rss+xml"/><item><title>Git - pushing to two remotes</title><link>https://blog.iankulin.com/git-pushing-to-two-remotes/</link><pubDate>Fri, 15 Dec 2023 00:00:00 +0000</pubDate><guid>https://blog.iankulin.com/git-pushing-to-two-remotes/</guid><description>&lt;p&gt;I am loving running a local Gogs instance - it&amp;rsquo;s nice pushing my git repos to a totally private hub that I know is backed up with all my other self-hosted infrastructure.&lt;/p&gt;
&lt;p&gt;Of course, there&amp;rsquo;s good reasons to have code in GitHub as well - my build-in-public philosophy, the vague possibility that some of it might be useful to someone, my contribution to our future AI overlords, and when I need to make some code linkable - for example from one of these posts. And of course there&amp;rsquo;s this bit of social-engineering which I assume was inspired by the bathroom decor in &lt;a href="https://i.pinimg.com/originals/94/23/85/9423854153f55938c454a061ad5462fe.gif"&gt;Veronica Mars&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-11-25-at-5.45.50-am.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Git is an amazing tool, so of course this is possible. Normally my workflow is that I &lt;code&gt;git init&lt;/code&gt; whenever I&amp;rsquo;m working on a new something, then at some point I think &amp;ldquo;I should really push all this so it&amp;rsquo;s backed up&amp;rdquo;. I create the repository for it on GitHub or Gogs via the web interface, then come back to my project and:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;git remote add origin git@github.com:IanKulin/test.git&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This is making the connection between my local project and the GitHub repo. I&amp;rsquo;d never really thought about what &lt;code&gt;origin&lt;/code&gt; meant in this context the hundreds of times I&amp;rsquo;ve previously typed it in, but actually it&amp;rsquo;s just the name we are giving to this connection. It&amp;rsquo;s just a convention to call it &amp;lsquo;origin&amp;rsquo;, it could just as easily be called &amp;lsquo;fred&amp;rsquo; or &amp;lsquo;github&amp;rsquo;. Since I am now planning to push to two separate remotes, it&amp;rsquo;s going to make sense to give them meaningful names. So in that case, we can do this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git remote add github git@github.com:IanKulin/test.git
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git remote add gogs http://ct-gogs/iankulin/test.git
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then, we can push with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git push github main
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git push gogs main
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You might be wondering what happens if you just do a &lt;code&gt;git push&lt;/code&gt; at this stage (or as I like to call it &amp;ldquo;&lt;em&gt;Pressing the &amp;lsquo;Publish Branch&amp;rsquo; button on the VS Code source control panel&amp;rdquo;&lt;/em&gt;). The answer is that at the command line you&amp;rsquo;ll get an error saying you haven&amp;rsquo;t specified the destination, or in VS Code, it will ask you which one.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-11-25-at-9.41.08-am.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;We can set the default remote with the -u flag when we&amp;rsquo;re pushing&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git push -u gogs main
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-11-25-at-9.46.26-am.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;Now the button in VS Code will say something &amp;ldquo;Sync Changes&amp;rdquo; and when you press it, it will only push to the remote we used in the last &lt;code&gt;-u&lt;/code&gt; push. Same thing if we &lt;code&gt;git push&lt;/code&gt; at the command line - it will work, but only push to the remote we used in the last &lt;code&gt;-u&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s also worth noting that when we&amp;rsquo;ve set the default remote with the &lt;code&gt;-u&lt;/code&gt; flag in a &lt;code&gt;push&lt;/code&gt;, it is also the default remote for pulling from. Essentially this remote becomes the source-of-truth.&lt;/p&gt;
&lt;p&gt;For me this setup is usually fine - I&amp;rsquo;m generally working on my local gogs remote, that&amp;rsquo;s the source of truth so I specify it as the default with the &lt;code&gt;push -u&lt;/code&gt;. Then, when I&amp;rsquo;m done, I manually push to github so I can share it. If it was a project I needed to work on with anyone else, that would have to be the other way around - I&amp;rsquo;d use GitHub (or GitLab, Bitbucket etc) as the source of truth, and probably not even worry about hosting a copy on my home network unless I was worried about the repo being deleted.&lt;/p&gt;</description></item><item><title>Gogs - your own tiny GitHub</title><link>https://blog.iankulin.com/gogs-your-own-tiny-github/</link><pubDate>Wed, 06 Dec 2023 00:00:00 +0000</pubDate><guid>https://blog.iankulin.com/gogs-your-own-tiny-github/</guid><description>&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-11-20-at-8.08.37-pm.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;(edit: - I&amp;rsquo;ve &lt;a href="https://blog.iankulin.com/gogs-gitea-forgejo/"&gt;had a rethink about&lt;/a&gt; my source hosting)&lt;/p&gt;
&lt;p&gt;Once you&amp;rsquo;re familiar with coding tools, like the excellent &lt;a href="https://code.visualstudio.com/"&gt;VS Code&lt;/a&gt;, and &lt;a href="https://git-scm.com/docs/git"&gt;git&lt;/a&gt;, it&amp;rsquo;s immediately apparent that these tools can be applicable for other purposes. A great example is that I now do my financial accounting in plain text (using &lt;a href="https://github.com/beancount/beancount"&gt;beancount&lt;/a&gt;). I have a python script that converts by bank account data in to the beancount format text files, I edit them in VS Code with a &lt;a href="https://marketplace.visualstudio.com/items?itemName=Lencerf.beancount"&gt;plugin&lt;/a&gt; that does the syntax highlighting and checks everything balances.&lt;/p&gt;
&lt;p&gt;Naturally, I want to version control that, so my text based accounts are all committed to git. But I don&amp;rsquo;t really want to push them up to GitHub, even to a private repo. I want to push them to a git server that&amp;rsquo;s available for me to pull down from anywhere, and is backed up with all my other data.&lt;/p&gt;
&lt;p&gt;It actually is possible to run a git server to do this with vanilla git, and I&amp;rsquo;m sure that&amp;rsquo;s how the hairy chested &lt;a href="https://www.linuxfoundation.org/blog/blog/classic-sysadmin-how-to-run-your-own-git-server"&gt;sysadmins of old&lt;/a&gt; do it. But I want a web gui a bit like GitGub that I&amp;rsquo;m familiar with. Of course, GutHub does all that other sweet stuff like CI/CD, but I don&amp;rsquo;t need that for my accounts.&lt;/p&gt;
&lt;p&gt;There are a couple of popular options for this job, one is &lt;a href="https://about.gitea.com/"&gt;Gitea&lt;/a&gt; which does lean into that CI/CD functionality, and the other is &lt;a href="https://gogs.io/"&gt;Gogs&lt;/a&gt;, which being a bit simpler, is also a bit simpler to get going. When I say simpler, it&amp;rsquo;s still massive overkill for my needs - you can have thousands of users, do pull requests, track issues, write project wikis - all that good stuff. It also has webhooks so you can knit together a pipeline with drone.io, Jenkins or other CI/CD tools. So I went with Gogs&lt;/p&gt;
&lt;h3 id="installing"&gt;Installing&lt;/h3&gt;
&lt;p&gt;It&amp;rsquo;s not mentioned on the &lt;a href="https://gogs.io/docs/installation"&gt;install page for Gogs&lt;/a&gt;, but there is an official &lt;a href="https://hub.docker.com/r/gogs/gogs/"&gt;container build&lt;/a&gt;. Possibly this is because there&amp;rsquo;s a couple of rough edges that I&amp;rsquo;ll get to shortly. I&amp;rsquo;ve talked before about how I like to run services in Docker on LXC, so I won&amp;rsquo;t go over that again. Here&amp;rsquo;s my docker-compose:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;version: &amp;#39;3&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;services:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; gogs:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; image: gogs/gogs
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; container_name: gogs
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ports:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &amp;#34;23:22&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &amp;#34;80:3000&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; volumes:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - ./data:/data
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; restart: always
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However, there is a gotcha I hadn&amp;rsquo;t encountered before - when I &lt;code&gt;docker compose up&lt;/code&gt; with this, I got the error &amp;ldquo;failed to register layer: unlinkat /app/gogs/docker/build: invalid argument&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.iankulin.com/images/screen-shot-2023-11-20-at-8.36.42-pm.png"&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-11-20-at-8.36.42-pm.png" width="900" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When I asked ChatGPT about this, she thought it might be to do with the storage driver. I didn&amp;rsquo;t know what that was so I spent time googling around.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.iankulin.com/images/screen-shot-2023-11-20-at-8.40.36-pm.png"&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-11-20-at-8.40.36-pm.png" width="900" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Pretty soon, I discovered &lt;a href="https://forum.proxmox.com/threads/docker-failed-to-register-layer-applylayer-exit-status-1-stdout-stderr-unlinkat-var-log-apt-invalid-argument.119954/"&gt;this thread&lt;/a&gt;. Part way down there&amp;rsquo;s the suggestion to edit &lt;code&gt;/etc/docker/daemon.json&lt;/code&gt; to add a different storage driver, followed by many comments of &amp;ldquo;Thanks!&amp;rdquo; and &amp;ldquo;That fixed it&amp;rdquo;. I followed that advice, (it uses a different driver &amp;ldquo;vfs&amp;rdquo; rather than &amp;ldquo;aufs&amp;rdquo; as suggested by ChatGPT) and then the container came up properly.&lt;/p&gt;
&lt;p&gt;With that out of the way, and the container live, if you go to the port you&amp;rsquo;ve specified in the docker-compose file (mine was :80), you&amp;rsquo;ll be greeted with the &amp;ldquo;Install Steps For First-time Run&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.iankulin.com/images/screen-shot-2023-11-20-at-8.54.19-pm.png"&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-11-20-at-8.54.19-pm.png" width="900" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;They are not joking. You won&amp;rsquo;t be able to guess these settings. I guess they haven&amp;rsquo;t put a lot of work into the container experience - some of these settings need to be for inside the container, and some are used for prompting the user, which are outside of the container settings. I suspect this rough edge is why the container install is not on the Gogs website yet.&lt;/p&gt;
&lt;p&gt;Anyway, after I&amp;rsquo;d ignored this suggestion, run into problems, google them, found closed issues where people had had the same problem and the devs pointed them to the perfectly clear guidelines we hadn&amp;rsquo;t read&amp;hellip;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll leave you to read the guidelines. The only other things of note is that I used the SQLite database to make my life simpler, and you don&amp;rsquo;t need to muck around making an admin account - it just makes the first person to log in the admin. Once that&amp;rsquo;s all done, you have to create a user account, then log in with it. You&amp;rsquo;ll be greeted by a reasonably familiar sight.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.iankulin.com/images/screen-shot-2023-11-20-at-9.07.30-pm.png"&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-11-20-at-9.07.30-pm.png" width="900" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you go ahead and create a repository in Gogs, it will give you the commands to push a repo up:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.iankulin.com/images/screen-shot-2023-11-20-at-9.09.28-pm.png"&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-11-20-at-9.09.28-pm.png" width="900" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;So let&amp;rsquo;s do that:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-11-20-at-9.21.38-pm.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;The back in our repo on Gogs:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.iankulin.com/images/screen-shot-2023-11-20-at-9.22.53-pm.png"&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-11-20-at-9.22.53-pm.png" width="1023" alt=""&gt;&lt;/a&gt;&lt;/p&gt;</description></item><item><title>New Project Routine</title><link>https://blog.iankulin.com/new-project-routine/</link><pubDate>Sat, 21 Oct 2023 00:00:00 +0000</pubDate><guid>https://blog.iankulin.com/new-project-routine/</guid><description>&lt;p&gt;I have a sort of muscle memory for starting little web projects now. I seem to have landed on node/express SSR apps with HTMX sprinkles. So it goes a bit like this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create a working directory - all lower case with a simple, but unlikely to be duplicated by me, name.&lt;/li&gt;
&lt;li&gt;Open the directory in vscode&lt;/li&gt;
&lt;li&gt;&lt;code&gt;npm init&lt;/code&gt; in the directory to create the &lt;code&gt;package.json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;create a &lt;code&gt;public&lt;/code&gt; sub directory, and drop &lt;a href="https://htmx.org/docs/#installing"&gt;&lt;code&gt;htmx.min.js&lt;/code&gt;&lt;/a&gt; in there, and create a &lt;code&gt;styles.css&lt;/code&gt; there. I&amp;rsquo;m always conflicted about what to do about this htmx dependency. I&amp;rsquo;d rather host it rather than use their CDN because &lt;a href="https://blog.wesleyac.com/posts/why-not-javascript-cdn"&gt;reasons&lt;/a&gt;. But I also feel bad about committing it on Github. I could .gitignore it, but then when I clone the project on the production server I&amp;rsquo;d need to add another step to download it. HTMX is only 44K, and Microsoft can afford the bandwidth, so for the moment I commit them, but I need a better solution for the future.&lt;/li&gt;
&lt;li&gt;using the git tools in vscode, add &lt;code&gt;.DS_Store&lt;/code&gt; to &lt;code&gt;.gitignore&lt;/code&gt; (which also creates it), then edit it to also ignore &lt;code&gt;node_modules&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;npm install express&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;npm install ejs&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;create a server.js, and add the &lt;a href="https://nodejs.org/en/docs/guides/getting-started-guide"&gt;hello world&lt;/a&gt; code&lt;/li&gt;
&lt;li&gt;create a &lt;code&gt;readme.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;commit these files as &amp;ldquo;initial&amp;rdquo;&lt;/li&gt;
&lt;li&gt;Create the repo on github with the same name - no readme and no licence. I do it this way for a couple of reasons - I want to find out at this point if I&amp;rsquo;ve already used this repo name, and I want it to give me the cut and paste commands to push the repository.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-09-25-at-9.55.46-am.png" alt=""&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Do those in the terminal.&lt;/li&gt;
&lt;li&gt;Refresh the github page, and add the licence by &lt;code&gt;Add File&lt;/code&gt;, name it LICENSE - this lets you choose the template you want. What I&amp;rsquo;d really like here is &amp;ldquo;GPL3 but giant cloud companies can&amp;rsquo;t make money from hosting it&amp;rdquo; - which I guess would be called the MongoDB license or something.&lt;/li&gt;
&lt;li&gt;Do &lt;code&gt;git pull&lt;/code&gt; in the terminal to check that&amp;rsquo;s all working&lt;/li&gt;
&lt;li&gt;&lt;code&gt;nodemon ./server.js&lt;/code&gt; then command click on the link to check everything&amp;rsquo;s working&lt;/li&gt;
&lt;li&gt;profit&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="express-skeleton"&gt;Express Skeleton&lt;/h3&gt;
&lt;p&gt;That&amp;rsquo;s my basic web app setup, but since this is an express app, and we&amp;rsquo;re using some EJS templating, there&amp;rsquo;s some other starter files I like to create. Let&amp;rsquo;s start with our pages. I&amp;rsquo;ll need an index and a 404 page, and my pages are all going to have a header section as well as a nav and a footer. Something like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;─── views
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ├── 404.ejs
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ├── index.ejs
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; └── partials
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;    ├── footer.ejs
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;    ├── head.ejs
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;   └── nav.ejs
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To give you a flavour of how that all works, here&amp;rsquo;s a sample &lt;code&gt;index.ejs&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;!DOCTYPE html&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;html lang=&amp;#34;en&amp;#34;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;%- include(&amp;#39;./partials/head.ejs&amp;#39;) %&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;body&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;%- include(&amp;#39;./partials/nav.ejs&amp;#39;) %&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;div class=&amp;#34;content&amp;#34;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;h2&amp;gt;Hello world&amp;lt;/h3&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/div&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;%- include(&amp;#39;./partials/footer.ejs&amp;#39;) %&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/body&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/html&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then we need some basic routing in &lt;code&gt;server.js&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;const&lt;/span&gt; express &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; require&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#39;express&amp;#39;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;const&lt;/span&gt; app &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; express&lt;span style="color:#eceff4"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;const&lt;/span&gt; hostname &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#39;127.0.0.1&amp;#39;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;const&lt;/span&gt; port &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;3000&lt;/span&gt;&lt;span style="color:#eceff4"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;app&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;set&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#39;view engine&amp;#39;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#39;ejs&amp;#39;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;app&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;use&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;express&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;static&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#39;public&amp;#39;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;app&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;get&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#39;/&amp;#39;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#eceff4"&gt;(&lt;/span&gt;req&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; res&lt;span style="color:#eceff4"&gt;)&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; res&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;render&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#39;index&amp;#39;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt; title&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#39;Index&amp;#39;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1"&gt;//&lt;/span&gt;&lt;span style="color:#b48ead"&gt;404&lt;/span&gt; handling
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;app&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;use&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;function &lt;span style="color:#eceff4"&gt;(&lt;/span&gt;req&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; res&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; next&lt;span style="color:#eceff4"&gt;)&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; res&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;status&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#b48ead"&gt;404&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;render&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#39;404&amp;#39;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt; title&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#39;404&amp;#39;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; url&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; req&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;url &lt;span style="color:#eceff4"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#eceff4"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;app&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;listen&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;port&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; hostname&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#eceff4"&gt;()&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; console&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;log&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#bf616a"&gt;`&lt;/span&gt;Server running at http&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;//$&lt;/span&gt;&lt;span style="color:#eceff4"&gt;{&lt;/span&gt;hostname&lt;span style="color:#eceff4"&gt;}:&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;$&lt;/span&gt;&lt;span style="color:#eceff4"&gt;{&lt;/span&gt;port&lt;span style="color:#eceff4"&gt;}&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;/&lt;/span&gt;&lt;span style="color:#bf616a"&gt;`&lt;/span&gt;&lt;span style="color:#eceff4"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#eceff4"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And, lastly, a bit of CSS to make it beautiful.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;@viewport {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; width: device-width ;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; zoom: 1.0 ;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;} 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;body{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; max-width: 1200px;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; font-family: Tahoma, Arial, Helvetica, sans-serif;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; margin: 0;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;nav {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; position: fixed; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; top: 0; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; width: 100%; 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; overflow: hidden;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; background-color: #EEE;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;nav li {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; display: inline-block;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; padding: 0;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;nav a {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; display: inline;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; color: #333;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; text-align: center;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; padding: 17px 8px;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; text-decoration: none;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;nav a:hover {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; background: #ddd;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; color: black;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;nav ul {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; padding-inline-start: 4px;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/* push content down below the nav bar */
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.content {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; padding: 50px 10px 10px 10px;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;footer {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; width:100%;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; position:absolute;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; bottom:0;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; left:0;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; color: #757171;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; text-align: center;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; margin: 80px auto 20px;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; background-color: #EEE;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;chefs_kiss.jpg&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-09-25-at-11.54.42-am.jpg" alt=""&gt;&lt;/p&gt;</description></item><item><title>Git/GutHub - macOS - marking file as executable</title><link>https://blog.iankulin.com/git-guthub-macos-marking-file-as-executable/</link><pubDate>Sun, 30 Apr 2023 00:00:00 +0000</pubDate><guid>https://blog.iankulin.com/git-guthub-macos-marking-file-as-executable/</guid><description>&lt;p&gt;I&amp;rsquo;m working on the world&amp;rsquo;s shortest shell script - it&amp;rsquo;s called by &lt;code&gt;cron&lt;/code&gt; to pull down a JSON weather report to a text file using &lt;code&gt;curl&lt;/code&gt; so I can expose it on an Nginx endpoint. The purpose is to allow me to hammer that weather API from multiple machines I control without violating the TOS of my free API key.&lt;/p&gt;
&lt;p&gt;Because I&amp;rsquo;m learning all the things, instead of just creating this on the VPS where it runs, it&amp;rsquo;s cloned from my GitHub repo for that machine. I&amp;rsquo;m creating and editing the file in VS Code on macOS, pushing to Github, then pulling the changes on the Ubuntu VPS. The intention is that this will eventually become automated with a Github action.&lt;/p&gt;
&lt;p&gt;The problem I&amp;rsquo;ve run into is that I want the file permissions so show the file is executable so when it arrives on the VPS - so no &lt;code&gt;chmod&lt;/code&gt; is required to make it usable.&lt;/p&gt;
&lt;p&gt;Some googling suggested that the executable flag (but none of the other file permissions) is stored and handled by git, and furthermore, there&amp;rsquo;s a git command to set it:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git update-index --chmod=+x bin/fetchWeather.sh 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So I wrote my (one line) script, applied the command above, committed and pushed, then pulled it down on the VPS and the bit wasn&amp;rsquo;t set. So somewhere in this chain there&amp;rsquo;s a problem.&lt;/p&gt;
&lt;p&gt;At this stage, it&amp;rsquo;s helpful to know that if the executable bit is set for a file, GitHub shows this in the header of the file where it says how many lines etc.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-04-22-at-4.26.25-pm.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-04-22-at-4.26.41-pm.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;In my case, it was showing that the file was not marked as executable in GitHub, so the problem was that the &lt;code&gt;git update-index&lt;/code&gt; was not working for me for some reason.&lt;/p&gt;
&lt;p&gt;A bit more investigation turned up that there&amp;rsquo;s a setting in the &lt;code&gt;.git/config&lt;/code&gt; file called &lt;code&gt;filemode&lt;/code&gt; that controls if the originating file system executable status is preserved. That sounded promising - I was expecting to find that is was set to false, and I could change it to true, and it would fix my problem. I had a quick look and, oh, it&amp;rsquo;s already set to true.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.iankulin.com/images/screen-shot-2023-04-22-at-4.36.54-pm.png"&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-04-22-at-4.36.54-pm.png" width="656" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Seems like it&amp;rsquo;s involved though, so perhaps (my thinking went) I should change it to false and see if the problem goes away&amp;hellip;. and it did. I changed this value to &lt;code&gt;false&lt;/code&gt;, applied the executable bit with the &lt;code&gt;git update-index&lt;/code&gt; command, committed, pushed it to GitHub (it was marked executable), pulled it down to the VPS, it was still marked executable!&lt;/p&gt;
&lt;p&gt;My whole tech life, I&amp;rsquo;ve never been happy with solutions to problems where I don&amp;rsquo;t understand the underlying reasons. If things just start working when you&amp;rsquo;re fiddling around and you&amp;rsquo;re not clear on why, it feels like they could change back with just as easily and with no more reason.&lt;/p&gt;
&lt;p&gt;A clue to what&amp;rsquo;s going on (many readers will already have figured this out) was given to me by ChatGPT. When I was asking it about this issue, it kept insisting I should &lt;code&gt;chmod&lt;/code&gt; the file to be executable before I committed it. I had to be really clear with it that this wasn&amp;rsquo;t possible on macOS because it doesn&amp;rsquo;t have that sort of file permissions&amp;hellip;&lt;/p&gt;
&lt;img src="https://blog.iankulin.com/images/cain.jpg" width="140" alt=""&gt;
&lt;p&gt;Of course, in fact, it does. &lt;a href="https://developer.apple.com/library/archive/documentation/Darwin/Conceptual/KernelProgramming/BSD/BSD.html"&gt;macOS is based on FreeBSD&lt;/a&gt; (&amp;ldquo;without the good bits&amp;rdquo; goes the old joke told at Unix conferences). I&amp;rsquo;d just somehow forgotten this - I guess in Linux I&amp;rsquo;m used to explicitly seeing them every time I look at a directory contents, but never see it on Mac. Even if you go into &amp;ldquo;Get Info&amp;rdquo; for a file in Finder on the mac, you can see the read/write permissions, but not the executable bit status.&lt;/p&gt;
&lt;p&gt;So how do you set and view the executable status on mac? Exactly the same as on any Unix.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.iankulin.com/images/screen-shot-2023-04-22-at-4.52.17-pm.png"&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-04-22-at-4.52.17-pm.png" width="1000" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I did that, and changed the /&lt;code&gt;git/config filemode&lt;/code&gt; back to &lt;code&gt;true&lt;/code&gt;. Committed and pushed the file up (without worrying about the &lt;code&gt;git update-index&lt;/code&gt;) and it showed up in GitHub as executable, pulled it down, still executable.&lt;/p&gt;</description></item><item><title>Committed</title><link>https://blog.iankulin.com/committed/</link><pubDate>Tue, 06 Dec 2022 00:00:00 +0000</pubDate><guid>https://blog.iankulin.com/committed/</guid><description>&lt;p&gt;I quite like logging into GitHub and seeing my commit history as the graph with the green dots. Once I get up to a year it would be a great thing to have on a T-Shirt.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2022-12-03-at-7.36.29-pm.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;d expect to be seeing the busy weekends, but Tuesday nights seem to be oddly productive. It could just be a start of the week energy thing - I have some other community obligations on a couple of Monday nights a month.&lt;/p&gt;
&lt;p&gt;git is an amazing tool - better that the commercial tool I used when I was programming a long way back. I really admire what the many open source programmers have put in to it. I also owe some gratitude to Microsoft for making GitHub available to newbs like me at no cost - it&amp;rsquo;s an great service.&lt;/p&gt;
&lt;p&gt;According to the graph, my first commits were on July 10. My first blog post was on the 5th, and I&amp;rsquo;m on a 154 once per day posting streak - although there&amp;rsquo;s a few two per day scattered through there when I&amp;rsquo;ve been on holidays. I&amp;rsquo;m only up to day 64 of the 100 Days of SwiftUI - so I clearly I haven&amp;rsquo;t been getting in an hour each day on that religiously, but overall, I&amp;rsquo;m pretty happy with my commitment to myself.&lt;/p&gt;</description></item><item><title>git stash</title><link>https://blog.iankulin.com/git-stash/</link><pubDate>Sat, 12 Nov 2022 00:00:00 +0000</pubDate><guid>https://blog.iankulin.com/git-stash/</guid><description>&lt;p&gt;When I was writing the blog post for the last project, I needed the &amp;ldquo;before&amp;rdquo; code to paste into the post. I&amp;rsquo;d committed that code, so a quick way to go back without losing my changes. I hadn&amp;rsquo;t committed the new code, so there is a super easy way to accomplish this.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git stash
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This grabs the code since the last commit and stashes it away, reverting the directory to the last committed version. I was able to copy the code I needed to the blog post, then to go back to my changes:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git stash pop
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2022-11-06-at-3.31.51-pm.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;It does get more complex than this - it&amp;rsquo;s git of course. It&amp;rsquo;s possible to stash multiple changes then pop them back, it&amp;rsquo;s also possible name them to selectively pop them, and to view the diffs. They are like little uncommitted branches - which can also be turned into branches. There&amp;rsquo;s a &lt;a href="https://www.atlassian.com/git/tutorials/saving-changes/git-stash"&gt;good outline here&lt;/a&gt; from Atlassian.&lt;/p&gt;</description></item><item><title>git - Rollback to last commit</title><link>https://blog.iankulin.com/git-rollback-to-last-commit/</link><pubDate>Tue, 08 Nov 2022 00:00:00 +0000</pubDate><guid>https://blog.iankulin.com/git-rollback-to-last-commit/</guid><description>&lt;p&gt;I&amp;rsquo;m on &lt;a href="https://www.hackingwithswift.com/books/ios-swiftui/dynamically-filtering-fetchrequest-with-swiftui"&gt;Project 12&lt;/a&gt; of the &lt;a href="https://www.hackingwithswift.com/100/swiftui"&gt;#100Days&lt;/a&gt; course, and like a number of earlier &amp;ldquo;projects&amp;rdquo; it&amp;rsquo;s not really a project, but a series of type-along tutorials. Often these have the same format - there&amp;rsquo;s a base amount of code to provide the setup, then this base is used to try each of the tutorial techniques. At the end of each technique, you delete all the new code you&amp;rsquo;ve done back to the original setup, and you&amp;rsquo;re ready for the next one.&lt;/p&gt;
&lt;p&gt;This is a perfect job for git. All I do is commit the code once the setup is done (and I&amp;rsquo;ve tested it). Then after I&amp;rsquo;ve mucked around, and want to go back.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git reset --hard
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In fact this is all so simple, it&amp;rsquo;s probably the perfect use case for getting started with git even if you&amp;rsquo;ve never used it. The steps would be:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;On a system with git installed (which includes macOS)&lt;/li&gt;
&lt;li&gt;Open a terminal window, and navigate to the directory you want to be able to rollback later&lt;/li&gt;
&lt;li&gt;&lt;code&gt;**git init**&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Create all your content&lt;/li&gt;
&lt;li&gt;&lt;code&gt;**git add -A**&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;**git commit -m &amp;quot;Some message&amp;quot;**&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Make all your disposable changes, then when you&amp;rsquo;re done &lt;code&gt;**git reset --hard**&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>Git - make all the commits into a single commit</title><link>https://blog.iankulin.com/git-make-all-the-commits-into-a-single-commit/</link><pubDate>Sat, 29 Oct 2022 00:00:00 +0000</pubDate><guid>https://blog.iankulin.com/git-make-all-the-commits-into-a-single-commit/</guid><description>&lt;p&gt;When I&amp;rsquo;m following a tutorial app, I generally pause and type up the code as I go, and make local commits with appropriate messages. This is almost completely unnecessary, but it seems like a good habit and doesn&amp;rsquo;t cost me anything - I just tick the box for creating the git when I start the project, then it&amp;rsquo;s a couple of keystrokes (option-command-C) and I&amp;rsquo;m done.&lt;/p&gt;
&lt;p&gt;Most of the apps have a follow-along portion, then some challenges which involve minor changes to the app. When I get to the challenges I like to throw it up on Github - it&amp;rsquo;s conceivable it could help someone one day, or at the least, I&amp;rsquo;m helping to train &lt;a href="https://github.com/features/copilot"&gt;Microsoft&amp;rsquo;s AI&lt;/a&gt; to write shitty beginner code in exchange for free git server access.&lt;/p&gt;
&lt;p&gt;The early commits I do are no help to anyone, even me by that stage, and it feels somehow untidy to leave them in there, so I started to wonder if there was some branchy/rebasey way to eliminate them before I push it up.&lt;/p&gt;
&lt;p&gt;This and the related problems of just eliminating some of the recent commit history are clearly topics of interest - there&amp;rsquo;s many stackover flow posts and blog articles. But shout out to &lt;a href="https://stackoverflow.com/users/825/pat-notz"&gt;Pat Noz&lt;/a&gt;, for his suggestion - &lt;a href="https://stackoverflow.com/questions/1657017/how-to-squash-all-git-commits-into-one"&gt;just delete the .git directory and start over&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2022-10-27-at-8.39.02-pm.png" alt=""&gt;&lt;/p&gt;
&lt;p&gt;When you &lt;code&gt;git init&lt;/code&gt;, a hidden folder is created in the directory you init in called &lt;code&gt;.git&lt;/code&gt; - you don&amp;rsquo;t normally see these hidden folders, but if you press &lt;code&gt;command-shift-.&lt;/code&gt; you can see it. This directory holds all the data that allows the magic of git to happen. If you delete just this directory and it&amp;rsquo;s contents, it&amp;rsquo;s like you never used git on this code.&lt;/p&gt;
&lt;p&gt;So in Pat&amp;rsquo;s words:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;rm -rf .git
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git init
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git add .
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git commit
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Simple. Elegant. Obvious once you&amp;rsquo;ve had the suggestion.&lt;/p&gt;</description></item><item><title>Gitting Xcode to Push</title><link>https://blog.iankulin.com/gitting-xcode-to-push/</link><pubDate>Fri, 30 Sep 2022 00:00:00 +0000</pubDate><guid>https://blog.iankulin.com/gitting-xcode-to-push/</guid><description>&lt;p&gt;I&amp;rsquo;m very comfortable with doing all the routine git stuff from the command line, but it was bugging me that I hadn&amp;rsquo;t for the Xcode integration working. I was able to commit locally with no problem from Xcode, but could not push up to Github. It works fine from the command line, so the error about the change to a stronger SSH authentication didn&amp;rsquo;t really make sense to me.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2022-09-26-at-6.57.35-am.png" alt=""&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;ERROR: You&amp;rsquo;re using an RSA key with SHA-1, which is no longer allowed. Please use a newer client or a different key type&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="https://developer.apple.com/forums/thread/702389"&gt;This post&lt;/a&gt; from &lt;a href="https://developer.apple.com/forums/profile/pasllani"&gt;pasllani&lt;/a&gt; on the Apple Developer forums was super helpful, the only thing they missed was that you need to restart Xcode before it will work. The steps were:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Generate a new ECDSA SSH key with &lt;code&gt;ssh-keygen -t ecdsa -C &amp;quot;IanKulin@kulin.com.au&amp;quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Copy the key to the keyboard with &lt;code&gt;pbcopy &amp;lt; ~/.ssh/id_ecdsa.pub&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;On Github, add the new SSH key, and while you&amp;rsquo;re there, generate a new Token in Developer Tools&lt;/li&gt;
&lt;li&gt;In XCode, delete your github account, then recreate it specifying SSH and choose the ECDSA key. It will need the access token at this stage.&lt;/li&gt;
&lt;li&gt;Restart XCode&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="other-gitgithub-posts"&gt;Other git/Github posts&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Intro to git - &lt;a href="https://blog.iankulin.com/gitting-started/"&gt;Gitting Started&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Common git commands - &lt;a href="https://blog.iankulin.com/gitting-the-hang-of-it/"&gt;Gitting the Hang of it&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.iankulin.com/gitting-up-to-date/"&gt;Merge vs rebase&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.iankulin.com/create-an-empty-folder-on-github/"&gt;Create an Empty Folder on Github&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.iankulin.com/download-a-directory-from-a-github-repo/"&gt;Download a Directory from a Github repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.iankulin.com/how-to-download-a-file-from-github/"&gt;Download a File from Github&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Gitting up to date</title><link>https://blog.iankulin.com/gitting-up-to-date/</link><pubDate>Tue, 27 Sep 2022 00:00:00 +0000</pubDate><guid>https://blog.iankulin.com/gitting-up-to-date/</guid><description>&lt;p&gt;I&amp;rsquo;ve started the habit of branching my code for each feature or batches of features. This is not really needed, I&amp;rsquo;ve developing solo, and the code on &lt;code&gt;main&lt;/code&gt; is not in production. I could just go on committing, but part of my process is about becoming competent with git.&lt;/p&gt;
&lt;p&gt;There are a couple of git commands (&lt;code&gt;merge&lt;/code&gt; and &lt;code&gt;rebase&lt;/code&gt;) that mush code between branches together in different ways. The video below (from &lt;a href="https://www.udemy.com/user/manuel-lorenz/"&gt;Manuel Lorenz&lt;/a&gt; at &lt;a href="https://academind.com/"&gt;Academind&lt;/a&gt;) is a particularly clear look at these two commands.&lt;/p&gt;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
 &lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/CRlGDDprdOQ?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
 &lt;/div&gt;

&lt;p&gt;The discussion that follows is essentially just a re-hash of the video above, so if you think you&amp;rsquo;ve got it, you can leave now!&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the situation we start with. A &amp;ldquo;feature&amp;rdquo; branch was created at the point in time that the most recent commit on the master branch was &amp;ldquo;m2&amp;rdquo;. A couple of commits have been made to the feature branch, but meanwhile a further commit has been made on the master branch:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2022-09-24-at-7.00.08-pm.jpg" alt=""&gt;&lt;/p&gt;
&lt;p&gt;So, what are the options now? (this is just a rehash of the video above in my words, so if you already watched that, you may leave :- ) I&amp;rsquo;m going to use &amp;ldquo;master&amp;rdquo; in my discussions here since that&amp;rsquo;s what Manuel uses, but if you&amp;rsquo;re new to git and you&amp;rsquo;ve only ever seen &amp;ldquo;main&amp;rdquo; - they are just different names for the default branch, &amp;ldquo;main&amp;rdquo; is the current (and slightly better) preference for that name.&lt;/p&gt;
&lt;h3 id="merge"&gt;Merge&lt;/h3&gt;
&lt;p&gt;We could checkout the master branch, and merge feature into it with&lt;/p&gt;
&lt;p&gt;&lt;code&gt;git merge feature&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;That works, and our commit history for the master branch will look like this:&lt;/p&gt;
&lt;p&gt;M1 - M2 - F1 - F2 - M3 - Merge&lt;/p&gt;
&lt;h3 id="squash"&gt;Squash&lt;/h3&gt;
&lt;p&gt;To bundle up the feature branch and bring it across to master, we can (from the master branch) do:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;git merge --squash feature&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;That add all the feature changes to the current branch, but they&amp;rsquo;re not committed yet, so we&amp;rsquo;ll also:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;git commit -m &amp;quot;add feature&amp;quot;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The history of the master branch now will be:&lt;/p&gt;
&lt;p&gt;M1 - M2 - M3 - add feature&lt;/p&gt;
&lt;p&gt;So this is sort of neater, instead of a chronological history in the commits, we&amp;rsquo;re conceptually saying the feature work was all done in a single commit after the M3 change. But&amp;hellip; what if we wanted to keep the feature commit history?&lt;/p&gt;
&lt;h3 id="rebase"&gt;Rebase&lt;/h3&gt;
&lt;p&gt;Just to recap, although our master branch is up to m3, the feature branch was &lt;em&gt;based&lt;/em&gt; off m2. So if we had a look at the history of the feature branch (using git log) it looks like this:&lt;/p&gt;
&lt;p&gt;M2 - F1 - F2&lt;/p&gt;
&lt;p&gt;Rebasing it will look at the changes in feature then apply them to the current m3 commit in master. If we change to the feature branch and enter:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;git rebase master&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Now the feature history will be&lt;/p&gt;
&lt;p&gt;M1 - M2 - M3 - F1 - F2&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s sort of cool and all, basically the code in the feature branch is in the state that master would be after we&amp;rsquo;ve joined them back up, so we can go ahead and test and so on. But we haven&amp;rsquo;t actually joined up feature and master yet. To do that, we could to checkout the master branch, and rebase it from feature with:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;git rebase feature&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Then master will have the same history as feature: M1 - M2 - M3 - F1 - F2 That can just be committed and we&amp;rsquo;re good to go. Since the whole commit history is now in the master branch its fine to go ahead and delete the feature branch.&lt;/p&gt;
&lt;h3 id="gotcha"&gt;Gotcha&lt;/h3&gt;
&lt;p&gt;If you&amp;rsquo;re working in a team around a shared repository, it makes a lot of sense to rebase your local project from the current main/master in the shared repo. That way you can test for any problems your code might have with the current version, but, it&amp;rsquo;s bad form to rebase any commits that get pushed up. A good explanation for why this is can be found in the &lt;a href="https://git-scm.com/book/en/v2/Git-Branching-Rebasing"&gt;git docs&lt;/a&gt; - scroll down to &amp;ldquo;the perils of rebasing&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Instead what we should have done in the example above if we were planning on pushing the master would have been to rebase our feature branch as we did, but then change to the master branch and merge the feature branch in with&lt;/p&gt;
&lt;p&gt;&lt;code&gt;git merge feature&lt;/code&gt;&lt;/p&gt;</description></item><item><title>I git it*</title><link>https://blog.iankulin.com/i-git-it/</link><pubDate>Tue, 06 Sep 2022 00:00:00 +0000</pubDate><guid>https://blog.iankulin.com/i-git-it/</guid><description>&lt;img src="https://blog.iankulin.com/images/6y8jpj5f4el91.jpg" width="500" alt=""&gt;
&lt;p&gt;This meme&amp;rsquo;s been trending in the &lt;a href="https://old.reddit.com/r/ProgrammerHumor/comments/x3udcz/is_it_really_that_much_easy_because_in_the/"&gt;r/ProgrammerHumor subreddit&lt;/a&gt;, and although &amp;ldquo;to do literally anything&amp;rdquo; is a stretch, my git / github workflow is pretty routine now using the &lt;a href="https://xkcd.com/1597/"&gt;relevant xkcd&lt;/a&gt; method, but actually with quite a bit of understanding from the first half of the excellent &lt;a href="https://git-scm.com/book/en/v2"&gt;Pro Git book&lt;/a&gt;. I highly recommend it.&lt;/p&gt;
&lt;p&gt;I had in my goals to set up XCode for push (I think I probably just need to generate a token on GitHub and save it in xcode), so I will do that for completion, but I&amp;rsquo;m also enjoying my &lt;a href="https://blog.iankulin.com/oh-my-zsh/"&gt;pimped out terminal&lt;/a&gt; so I&amp;rsquo;m pretty much a git cli guy now.&lt;/p&gt;
&lt;p&gt;I may have gone overboard creating repos for every tiny app in my learning process - sorry Microsoft you have to host all of that for free. It is probably possible to have one repo, with a heap of separate projects inside it. That would require the ability to clone just a directory and it&amp;rsquo;s sub directories, which is something I don&amp;rsquo;t know how to do yet :-/&lt;/p&gt;
&lt;p&gt;&lt;em&gt;* Yes, I&amp;rsquo;m always going to do bad git puns in post titles.&lt;/em&gt;&lt;/p&gt;</description></item><item><title>Oh My Zsh</title><link>https://blog.iankulin.com/oh-my-zsh/</link><pubDate>Sat, 06 Aug 2022 00:00:00 +0000</pubDate><guid>https://blog.iankulin.com/oh-my-zsh/</guid><description>&lt;p&gt;I&amp;rsquo;ve been playing in the zsh shell since I started on the &lt;a href="https://blog.iankulin.com/missing-semester/"&gt;Missing Semester&lt;/a&gt;, and was wondering how to get my git branch name in the prompt. A few googles later, I&amp;rsquo;ve installed Oh My Zsh, and added the git and macos plugins. Pretty.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2022-08-02-at-7.26.08-pm.jpg" alt=""&gt;&lt;/p&gt;</description></item><item><title>Gitting the hang of it</title><link>https://blog.iankulin.com/gitting-the-hang-of-it/</link><pubDate>Thu, 04 Aug 2022 00:00:00 +0000</pubDate><guid>https://blog.iankulin.com/gitting-the-hang-of-it/</guid><description>&lt;p&gt;&lt;a href="https://xkcd.com/1597/"&gt;&lt;img src="https://blog.iankulin.com/images/git_2x.png" width="253" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I spent most of the day learning about, and practicing with git. I&amp;rsquo;ll list some of the resources at the bottom, but for the moment, this is my understandings / cheat sheet for git. Since this could conceivably turn up in someone&amp;rsquo;s google search, and slightly less conceivably be of some use, I will come back and edit it if there&amp;rsquo;s something bad/wrong here. Comments would be great if you think that&amp;rsquo;s the case.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s most likely to be useful to someone using Xcode, GitHub, and the command line for git on MacOS.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Start a new repository (repo)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;on GitHub create the repo, it doesn&amp;rsquo;t matter if you create any files in it - they will be wiped shortly&lt;/li&gt;
&lt;li&gt;while you are on GitHub, grab the SSH address for the repo - it&amp;rsquo;s under the green &amp;ldquo;Code&amp;rdquo; button. If your username is IanKulin and the new repo is named GitTest it would look like this &lt;code&gt;[git@github.com](mailto:git@github.com):IanKulin/GitTest.git&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;create your Xcode (or whatever) project. I use the repo name as the project (and therefore directory name) but that&amp;rsquo;s not strictly necessary. I navigate to the Developer folder, so the new project is created as a folder inside that. Then in terminal inside that new directory:&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git init&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;that marks it as a directory under source control, I usually drop a .gitignore in at this stage (more about that further down)&lt;/li&gt;
&lt;li&gt;we need to add the files and commit them to the local git repo:&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git add -A&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git commit -m &amp;quot;Initial commit&amp;quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;now we connect the local repo to your github repo&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git remote add origin [git@github.com](mailto:git@github.com):IanKulin/GitTest.git&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;that just sets up the name so you can use &lt;em&gt;origin&lt;/em&gt; now to refer to the remote repo&lt;/li&gt;
&lt;li&gt;push the local files up to github with&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git push -u -f origin main&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;main is the name of the branch - GitHub defaults to this. If you are looking at old tutorials they are probably using &lt;em&gt;master&lt;/em&gt; rather than &lt;em&gt;main.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Xcode&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;once a project is set up for git like this, Xcode will realise and use it to indicate changes in files, and mark them in the file navigator as &amp;ldquo;A&amp;rdquo; or &amp;ldquo;M&amp;rdquo; (need Added, or have been Modified). There is a Source Control menu that allows you to Add and Commit (more about these further down) to the local repo which work well, but I haven&amp;rsquo;t had any luck pushing up to GitHub with it - I do that from the command line. Doubtless this is something to do with the SSH key.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;About .gitignore&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;this config file is used by git to ignore the working files that shouldn&amp;rsquo;t be tracked - stuff like the different compile states and so on. Normally we&amp;rsquo;d only want the source, asset and make files etc - the stuff needed to recreate the project&lt;/li&gt;
&lt;li&gt;GitHub will create a default for the language you are using if you let it&lt;/li&gt;
&lt;li&gt;I usually add these lines to it:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;# MacOS&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.DS_Store&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;to show hidden files like this in Finder, COMMAND-SHIFT-DOT and the same to rehide them&lt;/li&gt;
&lt;li&gt;if you do that, you&amp;rsquo;ll also see the .git folder which is where git does all it&amp;rsquo;s magic.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;To check how things are going&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;use terminal in the directory where the repo is&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git status&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;you&amp;rsquo;ll see any files changed, or that need to be added, and if the local files are ahead of the last clone/push but not if they are behind the remote (GitHub) - until you do a &lt;code&gt;git fetch&lt;/code&gt;, the local git doesn&amp;rsquo;t know what changes have happened on the remote&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;To add any files you&amp;rsquo;ve created in the project to version control from the CLI&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;git add .&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;or of you just want to do a particular file&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git add&lt;/code&gt; &lt;filename&gt;&lt;/li&gt;
&lt;li&gt;this adds the files to the &amp;ldquo;staging area&amp;rdquo;  - they are having changes tracked, but they have not been &amp;ldquo;committed&amp;rdquo; to the local repository, or the remote&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;When done editing and adding files and they need to be &amp;ldquo;saved&amp;rdquo; to the local repository&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;this is called committing them&lt;/li&gt;
&lt;li&gt;do from the XCode &lt;em&gt;Source Control&lt;/em&gt; menu, or from the CLI with&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git commit -a -m &amp;quot;Message for commit&amp;quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;now they&amp;rsquo;ve been added to the local repo. If you do a git status it will tell you you are ahead of the remote&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;To &amp;ldquo;push&amp;rdquo; all the changes up to GitHub from the CLI&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;git push origin main&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;origin&amp;rdquo; is the address for the GitHub repo, it was set for us when we cloned the repo. &amp;ldquo;main&amp;rdquo; is the branch we&amp;rsquo;re pushing to.&lt;/li&gt;
&lt;li&gt;You can&amp;rsquo;t just  create a new branch with this push?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;To tag all the files in the current local repo&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;git tag -a v0.2 -m &amp;quot;Second  draft&amp;quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;the &lt;em&gt;v0.2&lt;/em&gt; is the tag and &lt;em&gt;&amp;ldquo;Second  draft&amp;rdquo;&lt;/em&gt; the description - change accordingly.&lt;/li&gt;
&lt;li&gt;This only does the local copy, so you need to push it to GitHub&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git push --tags&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;If you go and look on GitHub, the tags appear on the right under releases&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To clone from a tag point&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;git clone --depth 1 --branch v0.1 [git@github.com](mailto:git@github.com):IanKulin/TagTest.git&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;where v0.1 is the tag&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;--depth 1&lt;/code&gt; means you don&amp;rsquo;t get all the history with it&lt;/li&gt;
&lt;li&gt;alternatively, if you don&amp;rsquo;t need all the history you could just download the zip/tarball from GitHub&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some resources&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.digitalocean.com/community/tutorials/how-to-push-an-existing-project-to-github"&gt;How to Push an Existing Project to GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://missing.csail.mit.edu/2020/version-control/"&gt;MIT Missing Semester lecture - Version Control&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://git-scm.com/book/en/v2"&gt;Pro Git (book)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=DVRQoVRzMIY"&gt;Git Tutorial for Beginners - Git &amp;amp; GitHub Fundamentals In Depth&lt;/a&gt; (Tech with Tim video)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=USjZcfj8yxE"&gt;Learn git in 15 minutes&lt;/a&gt; - Colt Steele video&lt;/li&gt;
&lt;li&gt;&lt;a href="https://podcasts.apple.com/gb/podcast/ep-11-a-fail-story-for-every-topic/id1269435221?i=1000406471235"&gt;Fireside Swift podcast&lt;/a&gt; - Ep 11&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Gitting Started</title><link>https://blog.iankulin.com/gitting-started/</link><pubDate>Wed, 13 Jul 2022 00:00:00 +0000</pubDate><guid>https://blog.iankulin.com/gitting-started/</guid><description>&lt;p&gt;One of my early goals was to get in the habit of using version control with Git/Github, and I&amp;rsquo;ve got that sorted out today. My source was this excellent, very clear video from &lt;a href="https://www.youtube.com/channel/UCxA99Yr6P_tZF9_BgtMGAWA"&gt;Gwen Faraday&lt;/a&gt;. I highly recommend it if you are just starting.&lt;/p&gt;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
 &lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/RGOj5yH7evk?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
 &lt;/div&gt;

&lt;p&gt;It possibly helped that I&amp;rsquo;m also on mac, so I didn&amp;rsquo;t have to deal with the &amp;ldquo;or however that&amp;rsquo;s done on your system&amp;rdquo; type problems. Also, where things didn&amp;rsquo;t work as expected, the explanation about what was being done was clear enough that the problem was solvable. For example, the push command Gwen used was:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git push origin master
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;but GitHub had defaulted my initial branch to &amp;ldquo;main&amp;rdquo; rather than &amp;ldquo;master&amp;rdquo;. Easily fixed since she immediately explained what both of those modifiers were. The only other tiny bit of troubleshooting was that my git global config wasn&amp;rsquo;t set up, so my commit was followed by a big message pointing out that my real email address wasn&amp;rsquo;t used for the commit:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Committer: User Name &amp;lt;username@Ians-MacBook-Pro.local&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Your name and email address were configured automatically based
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;on your username and hostname. Please check that they are accurate.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;You can suppress this message by setting them explicitly. Run the
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;following command and follow the instructions in your editor to edit
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;your configuration file:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; git config --global --edit
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;After doing this, you may fix the identity used for this commit with:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; git commit --amend --reset-author
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It didn&amp;rsquo;t make any difference - the file I&amp;rsquo;d created locally pushed up to the GitHub repo just fine. When I did follow those instructions to edit the file, I suddenly needed to know how to use Vim (hint: &amp;ldquo;i&amp;rdquo; to go into insert mode for editing, then &amp;ldquo;:&amp;rdquo; for command mode and &amp;ldquo;x&amp;rdquo; to exit and save).&lt;/p&gt;
&lt;p&gt;The only real complexity in the whole process was generating the SSH key and saving that on GitHub to allow the push from your local directory up to the GitHub repository.&lt;/p&gt;
&lt;p&gt;Ignoring that, the process was:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Creating the repository via on GitHub&lt;/li&gt;
&lt;li&gt;Using &lt;code&gt;git clone&lt;/code&gt; to download the repository to the local machine and set it up for tracking in git&lt;/li&gt;
&lt;li&gt;Edit/create the files, however. Gwen used Visual Studio code, I used my tools&lt;/li&gt;
&lt;li&gt;Check status with &lt;code&gt;git status&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git add .&lt;/code&gt; to stage the new files and freshly edited files&lt;/li&gt;
&lt;li&gt;Commit those changes with &lt;code&gt;git commit -m &amp;quot;commit title&amp;quot; -m &amp;quot;description&amp;quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Then push them up to GitHub with &lt;code&gt;git push origin main&lt;/code&gt; where &amp;ldquo;main&amp;rdquo; is the branch name.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of that was by about the 25 minute mark in the video, and is probably enough for me to go away and get some practice with. The rest covers getting an already established local git repository to GitHub, branching, forking, undoing.&lt;/p&gt;</description></item></channel></rss>