Saturday 25 January 2014

Two birds; one... stone

G'day:
(If you got the allusion I was making in the title... you're a bad person).

OK, so two things have happened. I've been needing to get up to speed with Git for work-related purposed (we will presently - hopefully - be converting from SVN to Git), plus I also need to start participating in a coupla OS projects on Git. One of which I'm co-founder of ("ColdFusion UI the Right Way"). I do have an account on GitHub already, wherein I keep all the code metioned on this blog (and other bits and pieces): https://github.com/daccfml, however I pretty much just use that for backing-up, making-public and distributing it between my various computers. I can commit stuff and that's about it.

Also Andy Allan's recently written an essential blog article (I mentioned it yesterday, but here's the link again: "Version Control"), and this has already had some people come out of the wood work saying they don't use version- / source-control, excusing it as too hard. Nonsense.

By way of demonstration, I'm gonna work through getting Git up and running in this article. I've deinstalled all the Git stuff from my machine, and am starting again.

Download

I googled "git download", and unsurprisingly it's the first link. Front and centre are the download links. I'm on Windows, and the current version is 1.8.5.3, and the file is about 15MB.

Install

I dunno whether I need to, but I run the install file (Git-1.8.5.2-preview20131230.exe) as an administrator (I am literally doing this as I type, btw).

This starts off a fair straight forward install process. I select the following non-standard options:
  • Install to: c:\apps\git
  • Add "Git Bash  Here" to the right-click menu in Windows Explorer

I opt to use Git Bash only to start with, btw (this is the default, that said). I've been using Git Bash all along, so see no reason not to continue.

I also opt to leave the CRLF handling the default: checkout for Windows, commit for Unix. That gives a more transportable option should the files end up on a *nix system.

And now it installs. That's it.

Cheat

At this point I cheat slightly and re-check I can now connect again to my GitHub account before I continue, and I can. So it seems Git's installed OK locally.

Following a basic tutorial

There's a free Git orientation course on CodeSchool: tryGit. I'm gonna go through this both online, and follow through on my local Git install too.

Git Bash

As I said above, I'll be using Git Bash for this, which is a command-line client for Git. There's a bunch of GUI clients for Git too (including TortoiseGit, if you're an SVN / TortoiseSVN user, and wanting to ease your migration), but I find I get a feel for what's going on a bit more if I'm on a command line.

Git Bash (it's part of the main Git install, btw) is just what it sounds like: a Bash-like shell specifically for doing Git stuff. So when one runs it, one gets a command prompt:


NB: if you're one of these people that shrinks away a bit when you see a command-prompt, or a suggestion one needs to use one... please, for the love of god, get over yourself. You're an IT professional (supposedly). Command prompts shouldn't frighten you. They won't bite. And they're not complicated, it's just... well... typing stuff in, and getting results. Exactly the same as anything else you do on the computer.


Creating a repository

A repository is just a directory containing files which Git is "aware" of, and stores some info about (like what's changed, what needs committing, stuff like that). One can create a new Git repository anywhere, just by navigating to the directory one wants to be a git repository, and going git init:

Welcome to Git (version 1.8.5.2-preview20131230)


Run 'git help git' to display the help index.
Run 'git help <command>' to display help for specific commands.

adam.cameron@ACBIGLAPTOP ~
$ cd /c/temp

adam.cameron@ACBIGLAPTOP /c/temp
$ mkdir octobox

adam.cameron@ACBIGLAPTOP /c/temp
$ cd octobox

adam.cameron@ACBIGLAPTOP /c/temp/octobox
$ git init
Initialized empty Git repository in c:/temp/octobox/.git/

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$

Things to note:
  • In the screen examples as per above, I'm gonna make the stuff I type a pink-ish colour. The other colours are representative of the colours Git Bash uses on my install.
  • Git Bash pretty much works like a Windows command prompt, except one needs to use *nix style commands (so like mkdir instead of md, and ls instead of dir etc). One doesn't need to know too many of these commands, but general file-system navigation / management ones are handy.
  • I've created that "octobox" (not a new Ortus product, in case you were wondering) directory and made my repository in there as that's mirroring what the tutorial works with.
  • it was really easy to create a repository. Yeah: that's all I had to do.

Getting the "status" of the repository


Easy... git status:

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$ git status
On branch master

Initial commit

nothing to commit (create/copy files and use "git add" to track)

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$

Adding a file to source control

That status info is not so interesting, but if I add a file into the directory, we see more info:

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master
$ git status
On branch master

Initial commit

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        octocat.txt

nothing added to commit but untracked files present (use "git add" to track)

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$

See I've added that octocat.txt file... the status shows it's not in source control yet ("untracked"). that's one thing to remember with source control software, even though one might put files into a repository dirctory, they're not under source control until one makes them be.

One thing to remember about Git Bash here... it remembers your command history, so if you want to repeat an earlier command, just use the up/down arrows to traverse your history.

Right. To add the file into the repository so it can be source controlled, we add it in with... git add:

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$ git add octocat.txt

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$

(that wasn't very exciting, sorry). But if we get the status again:


adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$ git status
On branch master

Initial commit

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

        new file:   octocat.txt


adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$

We've told Git we want that file in source control, but it's still not under source control as we've not committed it yet. Note also here that Git's pretty helpful at telling you what's going on and what to do. If I do what it suggests, and recheck the status, I'm back to where I was before:


adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)

$ git rm --cached octocat.txt
rm 'octocat.txt'

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$ git status
On branch master

Initial commit

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        octocat.txt

nothing added to commit but untracked files present (use "git add" to track)

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$

Committing files

To start source-controlling the file we need to commit it, using git commit:

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$ git commit -m "Add cute octocat story"
[master (root-commit) ccc60e1] Add cute octocat story
 1 file changed, 1 insertion(+)
 create mode 100644 octocat.txt

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$

Here I've used the -m switch to allow me to add a commit message along with the commit itself. It's best to always add a message when committing, explaining why you're committing something.

If we do a status now, we see everything's safely in source control, and Git doesn't think we have anything to do:

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$ git status
On branch master
nothing to commit, working directory clean

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$

Adding multiple files

I've added some more files into that directory (following along with the tutorial):

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$ git status
On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)

        blue_octocat.txt
        octofamily/
        red_octocat.txt


nothing added to commit but untracked files present (use "git add" to track)

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$

It's not apparent from that display, but there are files in that octofamily/ directory too (momma_octocat.txt and baby_octocat.txt. Hey... I did not decide on those names myself, OK?)

Here's where I got tricked by the tutorial. Well: by my not paying attention to the tutorial. The next step is to add all those files, and the tutorial says to do this:

git add '*.txt'

So I duly typed in this, and ran it:

git add *.txt

And the results were:

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$ git add *.txt

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        new file:   blue_octocat.txt
        new file:   red_octocat.txt

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        octofamily/

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$

Notice how the octofamily subdirectory has not be added. It turns out - and this is the first unintuitive thing I have encountered with Git, that the single quotes are meaningful, and in this case seem to mean "do it recursively". Or something. I would have expected a -r switch or something, TBH.

I then tried to back-out of that add, and got into more trouble:

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$ git rm --cached '*.txt'
rm 'blue_octocat.txt'
rm 'octocat.txt'
rm 'red_octocat.txt'

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        deleted:    octocat.txt
Untracked files:
  (use "git add <file>..." to include in what will be committed)

        blue_octocat.txt
        octocat.txt
        octofamily/
        red_octocat.txt


adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$

Dammit! Now I've gone and said I want to remove octocat.txt from source control. Which is not what I wanted. I just wanted to revert my most recent add operation.

Fortunately the remedy is right there on the screen:

(use "git reset HEAD <file>..." to unstage)

(HEAD, btw, is just a reference to the most recent commited revision. It's standard source-control jargon).

So, anyway, I do that to get back to where I was: after adding/committing octocat.txt, but before adding the other files. Then I do what I was actually told to do, and things work much better:

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$ git reset HEAD

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$ git status
On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)

        blue_octocat.txt
        octofamily/
        red_octocat.txt

nothing added to commit but untracked files present (use "git add" to track)

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$ git add '*.txt'

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        new file:   blue_octocat.txt
        new file:   octofamily/baby_octocat.txt
        new file:   octofamily/momma_octocat.txt
        new file:   red_octocat.txt


adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$

The tutorial then gets me to commit that change:


adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$ git commit -m 'Add all the octocat txt files'
[master 29041cb] Add all the octocat txt files
 4 files changed, 4 insertions(+)
 create mode 100644 blue_octocat.txt
 create mode 100644 octofamily/baby_octocat.txt
 create mode 100644 octofamily/momma_octocat.txt
 create mode 100644 red_octocat.txt

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$

Looking at the activity log

There's not much to this (in the context of the tutorial), it's just git log:

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$ git log
commit 29041cb7c7a6bf1fc9a2673a5efc2fcbc5b4b6f8
Author: Adam <adamcameroncoldfusion@gmail.com>
Date:   Sat Jan 25 14:00:23 2014 +0000

    Add all the octocat txt files

commit ccc60e1a5598e9b7b82173601b30b02740f90cc5
Author: Adam <adamcameroncoldfusion@gmail.com>
Date:   Sat Jan 25 13:10:23 2014 +0000

    Add cute octocat story

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$

Creating an account and repository on Github

Next the tutorial is gonna get me to push all that stuff up ot GitHub. For me to do this here, I'm gonna have to create a repo on GitHub to receive it.

I've already got an account on GitHub, but if you don't have one... go create one. I can't recall what's involved, but it's basically just signing up to the site, from memory.

From there I have created a new repository called , which has the URL https://github.com/daccfml/git-tutorials.

Back to the Tutorial

Pushing a local repository to Github

Now... to get the stuff in my local repository up to GitHub, I need to do this:

git remote add origin https://github.com/daccfml/git-tutorials.git


OK... here goes...

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$ git remote add origin https://github.com/daccfml/git-tutorials.git

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$

[dejectedly] Oh. Well that wasn't very exciting :-(

Had I actually RTFMed, then I'd be reminded that all this does is set up the remote connection. It doesn't actually do anything. OK. It's when I tell git to push (using git push) the local stuff to the remote that things happen...

We have a problem


adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$ git push -u origin master
fatal: could not read Username for 'https://github.com': No such file or directory

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$

Oooookay. That is not what I expected. But I googled the error, and found a StackOverflow question (with various answers), and am now working through the instructions in this document: "Generating SSH Keys".

Yeah, that fixed it. basically there's a bug of some description in Git 1.8.5, meaning I need to use SSH instead of HTTPS. Or I could downgrade to 1.8.4. I opted to use SSH instead.

Having followed those instructions, I need to get rid of that HTTPS-based remote I added before, and add a SSH one instead (all this is in those docs I link to above... I had no idea about any of this before reading 'em):

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$ git remote remove origin

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$ git remote add origin git@github.com:daccfml/git-tutorials.git


adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$

Back on track: pushing the files

Right, so now we should be able to push those files!

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$ git push -u origin master
Warning: Permanently added the RSA host key for IP address '192.30.252.131' to t
he list of known hosts.
Counting objects: 6, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (6/6), 570 bytes | 0 bytes/s, done.
Total 6 (delta 0), reused 0 (delta 0)
To git@github.com:daccfml/git-tutorials.git
 * [new branch]      master -> master
Branch master set up to track remote branch master from origin.

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$

Yay! And I can verify the files are actually on GitHub by eyeballing them on github itself:


Cool! :-)

Cloning

The tutorial calls for a bit of make-believe here, as it just "pretends" there's been remote activity and then demonstrates a git pull operation. However I've leapt over onto my other computer, and cloned (read: downloaded) the repository onto it using git clone:


C:\temp>git clone https://github.com/daccfml/git-tutorials.git
Cloning into 'git-tutorials'...
remote: Counting objects: 6, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 6 (delta 0), reused 6 (delta 0)
Unpacking objects: 100% (6/6), done.

C:\temp>

I then updated a coupla files, and pushed them back up to GitHub. So now I can do an actual pull, and get some updates.

Pulling

Getting updates from a remote repository is just a matter of doing a git pull, as mentioned above:

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$ git pull origin master
remote: Counting objects: 6, done.
remote: Compressing objects: 100% (1/1), done.
remote: Total 4 (delta 1), reused 4 (delta 1)
Unpacking objects: 100% (4/4), done.
From github.com:daccfml/git-tutorials
 * branch            master     -> FETCH_HEAD
   29041cb..82ec524  master     -> origin/master
Updating 29041cb..82ec524
Fast-forward
 octocat.txt    | 2 +-
 remote_cat.txt | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)
 create mode 100644 remote_cat.txt

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$

What I did on the remote machine is to edit octocat.txt, and add a new file remote_cat.txt. This reports here as a deletion and an add on octocat.txt ("deleting" the old line, and replacing it with two new lines I guess... despite the fact one of the new lines was actually the same old line? Odd), and an add on remote_cat.txt.

Diffing

I've snuck in and modified file. We can see this with git diff:

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$ git diff head
diff --git a/octocat.txt b/octocat.txt
index 5930c21..7a492a7 100644
--- a/octocat.txt
+++ b/octocat.txt
@@ -1 +1,2 @@
-octocat.txt updated remotely
\ No newline at end of file
+octocat.txt updated remotely
+and updated again locally, but not committed yet

\ No newline at end of file

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$

We can tell we have a local change to octocat.txt which hasn't been committed yet. I've changed its text from this:
octocat.txt updated remotely

To this:
octocat.txt updated remotely
and updated again locally, but not committed yet

Using a variation of git diff, we can see files that have been added to the file system and staged for commit (so git added) but not committed yet:

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$ git diff --staged
diff --git a/octofamily/octodog.txt b/octofamily/octodog.txt
new file mode 100644
index 0000000..e69de29

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$

Here I've added a file octodog.txt, which still needs to be committed.

Undoing

Next the tutorial looks at git checkout which - in this example - is used to roll-back those earlier changes to octocat.txt, You'll recall we'd changed the file, but not committed it (see below for a reminder), and we then use git checkout to checkout the previously committed version of that file, in effect reverting the uncommitted changes to it:

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$ git diff
diff --git a/octocat.txt b/octocat.txt
index 5930c21..7a492a7 100644
--- a/octocat.txt
+++ b/octocat.txt
@@ -1 +1,2 @@-octocat.txt updated remotely\ No newline at end of file
+octocat.txt updated remotely
+and updated again locally, but not committed yet
\ No newline at end of file

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$ git checkout -- octocat.txt

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.

nothing to commit, working directory clean

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$

Branching

Creating a branch is predictably easy. One uses git branch:

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$ git branch clean_up

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.

nothing to commit, working directory clean

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$

Note that we're still in the master branch though. We've just created the clean_up branch. We can verify this with another call to git branch:

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$ git branch
  clean_up
* master

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$

Here the asterisk indicates which branch we're currently in. We can switch to the clean_up branch simply by using git checkout:

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$ git checkout clean_up
Switched to branch 'clean_up'

adam.cameron@ACBIGLAPTOP /c/temp/octobox (clean_up)
$ git branch
* clean_up
  master

adam.cameron@ACBIGLAPTOP /c/temp/octobox (clean_up)
$

Removing files

Next in the tutorial we are getting rid of everything in the branch. This is done with git rm. It seems to work the same as git add, just in reverse (including that subtle difference between using single quotes and not using single quotes):

adam.cameron@ACBIGLAPTOP /c/temp/octobox (clean_up)
$ git rm *.txt
rm 'blue_octocat.txt'
rm 'octocat.txt'
rm 'red_octocat.txt'
rm 'remote_cat.txt'

adam.cameron@ACBIGLAPTOP /c/temp/octobox (clean_up)
$ git reset HEAD
Unstaged changes after reset:
D       blue_octocat.txt
D       octocat.txt
D       red_octocat.txt
D       remote_cat.txt

adam.cameron@ACBIGLAPTOP /c/temp/octobox (clean_up)
$ git checkout -- .

adam.cameron@ACBIGLAPTOP /c/temp/octobox (clean_up)
$ git status
On branch clean_up
nothing to commit, working directory clean

adam.cameron@ACBIGLAPTOP /c/temp/octobox (clean_up)
$ git rm '*.txt'
rm 'blue_octocat.txt'
rm 'octocat.txt'
rm 'octofamily/another_remote_cat.txt'
rm 'octofamily/baby_octocat.txt'
rm 'octofamily/momma_octocat.txt'
rm 'red_octocat.txt'
rm 'remote_cat.txt'

adam.cameron@ACBIGLAPTOP /c/temp/octobox (clean_up)
$

Here I've done a git rm both without quotes and with quotes, in turn. And you can see the lack of recursion in the former, compared to the latter.


Merging a branch

I committed that deletion (just with git commit), and switched back to the master branch (git checkout). Now I'm gonna merge clean_up back into master (in effect, deleting all those files in master as well). This is done with git merge:

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.

nothing to commit, working directory clean

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$ git merge clean_up
Updating 4d73005..053dabe
Fast-forward
 blue_octocat.txt                  | 1 -
 octocat.txt                       | 1 -
 octofamily/another_remote_cat.txt | 1 -
 octofamily/baby_octocat.txt       | 1 -
 octofamily/momma_octocat.txt      | 1 -
 red_octocat.txt                   | 1 -
 remote_cat.txt                    | 1 -
 7 files changed, 7 deletions(-)
 delete mode 100644 blue_octocat.txt
 delete mode 100644 octocat.txt
 delete mode 100644 octofamily/another_remote_cat.txt
 delete mode 100644 octofamily/baby_octocat.txt
 delete mode 100644 octofamily/momma_octocat.txt
 delete mode 100644 red_octocat.txt
 delete mode 100644 remote_cat.txt

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$

And to push that lot up to GitHub, we just do another git push:

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$ git push
warning: push.default is unset; its implicit value is changing in
Git 2.0 from 'matching' to 'simple'. To squelch this message
and maintain the current behavior after the default changes, use:

  git config --global push.default matching

To squelch this message and adopt the new behavior now, use:

  git config --global push.default simple

See 'git help config' and search for 'push.default' for further information.
(the 'simple' mode was introduced in Git 1.7.11. Use the similar mode
'current' instead of 'simple' if you sometimes use older versions of Git)

Counting objects: 3, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (1/1), done.
Writing objects: 100% (2/2), 203 bytes | 0 bytes/s, done.
Total 2 (delta 0), reused 0 (delta 0)
To git@github.com:daccfml/git-tutorials.git
   4d73005..053dabe  master -> master

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$

Most of that bumpf is irrelevant to what I was doing, and it's actually pretty cool that Git tells me that a change is afoot and lets me know how to deal with it.

If we have a peek at GitHub now, all the files are gone:


Deleting a branch

Lastly, we can get rid of that clean_up branch now:

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$ git branch -d clean_up
Deleted branch clean_up (was 053dabe).

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$ git branch
* master

adam.cameron@ACBIGLAPTOP /c/temp/octobox (master)
$

Note there's just the one branch, master, now.

Conclusion

That was the end of the tutorial. Please note that it would have taken a lot longer to read through all this than the tutorial takes to work through. It's about 15-30min all-up, depending on how long you dwell on things.

I actually learned quite a bit from this tutorial, even though it was the second time I did it. I guess I read up a lot more this time, plus the act of blogging it makes me pay more attention to what it was saying. Some of those concepts are more firmly in my head now. Hopefully they'll stick.

As a quick recap, we covered these Git commands during the tutorial:
That's a fair swag of stuff. And that's about enough for me sitting in front of a computer today (this has taken about 6h to write!).

Righto.


--
Adam