There’s a lot to Git and there’s tons of information all over the web about it. There’s so much information out there that you might feel overwhelmed when you first start trying to learn what Git is and how to use it. The purpose of this blog article is to help you install Git, teach you a few basics, and point you in the right direction to learn more.
I’ll start with a little background information: Back in 2009 when I started blogging on this site, I used the TechNet script repository to share my PowerShell code that I wrote about in my blog articles. Then in 2014, I started using GitHub instead of the TechNet script repository to accomplish the same sort of thing. I primarily used both as a way to share my code. I really wasn’t taking advantage of the source control features in GitHub other than using it as a way to get back to a previous major version. I would develop my scripts outside of what GitHub was aware of, placing the finished product in the default master branch that GitHub created, create a commit, and sync those changes to the online repository. Needless to say it was a haphazard process especially when trying to collaborate with others.
So I decided to start learning Git which is what GitHub is built on. I know there are PowerShell cmdlets for Git, but I felt that learning pure Git would give me a better understanding and then I could learn the PowerShell cmdlets for it.
The first resource that you need to know about is the home page for Git. From there you can download Git for Windows or for other operating systems that you plan to run it on. The install is a clicker-size (even the click-next admin can install it). You’re safe taking all the default options during the install.
While I won’t get bogged down in the details, these particular options have to do with sharing your code with people running different operating systems. Take the defaults and move on:
I’ve launched Git Bash. There’s also Git CMD if you feel more comfortable with it, although all of the examples I’ll show in this blog article use Git Bash (on Windows).
Coming from a PowerShell background, the first thing I wanted to know was how to use Git’s help
system. Typing git help
shows some basic help information. Typing git help help
opens more
detailed help information in a webpage.
git help
If you’re looking for help on a specific command, type git help <command_name>
and the help page
for that command will be opened as a webpage. The following example opens the help information for
the git init
command:
git help init
The following command shows the version of Git that you’re currently running. Notice that version begins with two dashes and that’s something you’ll find common to all parameters that are spelled out (if the parameter is a single letter, it only uses a single dash):
git --version
One of the first things you’ll want to do is configure Git. At a minimum, set the user name and email address since this information will be used in all of your commits. Remember that if you’re sharing any of your Git repositories publicly online, this information (specifically your email address) will be made publicly available. For this reason, I’ve specified my private GitHub email address instead of my real email address.
git config --global user.name "your name"
git config --global user.email "your email address"
The previous commands set those configuration options globally for your user. It’s also possible to
set these options at the machine and/or repository level. To learn more run git help config
.
You can verify this information was indeed set as shown in the following example:
git config user.name
git config user.email
You could also list all of the contents of the global config file by running the following command:
git config --list
I want to create a new repository on my machine to keep track of the changes I make to my MrSQL
PowerShell script module. I create a directory named MrSQL
which will be used as the working
folder for this Git repository. I change into that directory and then run the git init
command to
initialize a new git repository:
mkdir MrSQL
cd MrSQL
git init
That creates a hidden .git folder which is what keeps track of your changes (don’t mess with this folder if you value the data in your repository):
ls -a
I’ve also placed a PowerShell script module (.psm1) and manifest (.psd1) in the folder shown in the previous example that I want Git to keep track of the changes for.
The git status
command shows the current status of the working folder:
git status
Notice in the previous example, there are two untracked files that Git is aware of but not currently keeping track of.
You have to tell Git what files to keep track of. I want to track all files that are currently in
the working folder so I’ll run git add .
to add all of them to the staging area which is
sometimes referred to as an index. Then when I run git status
again, you see that both files are
staged but not committed:
git add .
git status
![git101-10a.jpg]](git101-10a.jpg)
As you can see in the previous example, many commands give you tips when they’re run. You can learn a lot by reading through these tips.
To commit these changes to the repository, use the git commit
command:
git commit -m "Added MrSQL script module and manifest files."
Notice that the repository is now up to date with what’s in the working folder:
git status
The git log
command shows the history of the repository:
git log
Notice that the commit is referenced by a SHA1 hash (the 40 character hexadecimal number in yellow next to the word commit).
Now I’m going to tag that commit with a human readable name so I’ll know that it’s version 1.0 of my MrSQL module:
git tag v1.0 -m "MrSQL PowerShell Module Version 1.0" 2ae04e06d07fe8b21be7167a0cb099a42741ad8b
I’m going to be working on a new version of my MrSQL module. I’ll create a development branch so
that my changes don’t accidentally get deployed before they’re ready. By default, the git branch
command creates a new branch that’s based off of the code that’s committed to whatever branch is
currently checked out. I think of a new branch as an isolated environment.
The git checkout
command places the code that’s in the specified branch into the working folder.
If the working folder currently has any unsaved changes, you’ll get a warning and you’ll have a
chance to either commit or stash the changes because checking out another branch removes whatever is
currently in the working folder.
git branch dev
git checkout dev
ls
I’ve now completed my changes to my MrSQL module and I’m ready to commit the changes to the repository. Remember to commit and commit often. At this point the changes are not saved except to the files that exist in the working folder.
Notice what the file system currently knows about versus what Git knows about for the working folder:
ls
git ls-files
The git status
command shows that two files have been modified and several files have been added
that are not currently tracked:
git status
The git diff
command can be used to view the specific details of what’s different between the
files that are currently in the working folder versus what the staging area is aware of. This
information is displayed a page at a time. Press the spacebar
to page down to the next page or q
to quit.
git diff
Although the two modified files were previously added to the staging area to be tracked, they still have to be added again. Any time a file in the working folder is changed whether it’s already being tracked or not, it must be added to the staging area first before it can be commited to the repository. What I could do since the two modified files were already being tracked is to specify the -a parameter when performing a commit to automatically add and commit them with a single command. I’ll show you the problem this creates if you have both tracked and untracked files that you want in the same commit:
git commit -a -m "Moved functions from PSM1 file to PS1 files."
git status
As you can see, the shortcut used in the previous example to add and commit with a single command
only works for files that are already being tracked. What I should have done in this scenario is to
add all of the files to the staging area with the git add
command and then commit them so they
would all be in the same commit. The problem now is that I committed those two files to the
repository and I meant to commit all of the changes. I want to fix this without having to performing
another separate commit and I also don’t want to loose any of the history of what’s been done.
Here’s what the git log
command currently shows:
git log --oneline
Instead of trying to use the git reset
command, I’ll go ahead and add all of those untracked files
in the working folder to the staging area:
git add .
git status
Use the git diff
command except with the staged
parameter to see the detailed differences
between the files in the staging area versus the ones that were previously committed to the
repository:
git diff --staged
Now I’ll amend the previous commit, adding whatever changes exist in the staging area to it:
git commit --amend
The previous command opened Vim since I didn’t specify the -m
parameter along with a commit message,
but since I didn’t want to change the message, I simply pressed :q
to exit. You can change the
default editor to Notepad using:
git config --global core.editor "notepad"
Now I’ll change back to the master branch. Notice what files are in the working folder while I have the files from the dev branch checked out. It’s important to note that checking out a branch changes the actually files that are located in the working folder. The physical location on disk does not change. After checking out the master branch, all of the files that were in the working folder are removed and replaced by the ones from the most recent commit of the master branch. I could also checkout a previous commit of a branch by specifying a tag name or SHA1 hash of a commit to check out an older version of the files.
ls
git checkout master
ls
Since I’ve completed my changes to the MrSQL PowerShell module and I’m ready for those changes to go
into production, I now need to merge those changes from the dev branch into master so they’re placed
in the production code base which is what I’m using the master branch for. All I have to do is run
the git merge
command, specifying the branch to merge from and it will be merged into the checked
out branch (which is master). Since no commits have occurred in the master branch since the dev
branch was created, a fast-forward merge is performed:
git merge dev
With fast-forward merges, a commit isn’t performed after the merge occurs, but it doesn’t need to since it only fast-forwards up to the most recent commit from the dev branch:
ls
git log --oneline
I’ll create another tag since this new version is going to be version 2.0 of my MrSQL PowerShell module:
git tag v2.0 -m "MrSQL PowerShell Module Version 2.0" 5717744
git tag
Tags remind you which commit is what release version because there may be hundreds of commits between versions. I can also checkout a specific version of the code that’s stored in a branch based on the tag name if I ever need to fix a bug in a previously released version.
Want to learn more? Keep an eye on this blog site.
You can download the eBook version of Pro Git 2nd Edition for free (it’s open source). You can also try out Git from code school without having to install anything. Both of these resources can also be found on the home page for Git.
Update 3/28/16
Additional related blog articles on this site:
- Getting Started with the Git Version Control System – Part 2
- Configuring the PowerShell ISE for use with Git and GitHub
- Git status doesn’t know if your local repository is out of date
µ