Getting Started with Git for the Windows Developer (Part III) - Working with Files Using Bash

Posted on September 18 2012 04:14 PM by John Atten in CodeProject, Git   ||   Comments (0)

Up to this point . . .

This is the third part in a series focused on getting familiar with Git for Windows developers. The series assumes little or no experience using the command line. If you missed the first few posts, here is what we have covered so far:

In the previous post, we learned how to navigate directories within the Windows file system, create new directories, and delete directories. Now let’s look at creating files, and performing rudimentary (VERY rudimentary) text editing from the Bash command prompt.

Before We Proceed . . .

Let’s create a directory to use for the following examples. Open your Bash Command Line Interface (CLI) and make sure you are in your default Windows user folder. Create a new directory within your user folder called BashExcercises, and then move into that directory (Review the previous post if you are unsure how to do this):

Create a Directory for the Following Exercises


Also remember, when we are explaining syntax, we will often use square brackets to denote optional items, and angle brackets to denote use-provided content. In the following:

mkdir [options] <FileName>

We do not type the square brackets or angle brackets. The [options] are, well, optional, meaning there may be none or there may be many, and the <Filename> is required and provided by the user.

Bash: Create/Edit Files (touch/echo)

There are a couple of ways to create a new file using the Bash command prompt. The most basic is the touch command. The purpose of the touch command is ostensibly to change/modify the date/time stamps of files. However, it is commonly used to create new files as well, since, when used without any optional arguments, it does just that: creates a new file, with a date stamp.

Using the Touch Command to Create a New Text File

The syntax for the touch command is

Create a new file with a date stamp:
touch [options] <filename>


There are a number of options for use with the touch command, but for now, we are going to focus on simple file creation, and we won’t be using any of the options. If we want to create a simple text file, we can type:

Create a new Text File Named MyNewTextFile:
$ touch MyNewTextFile.txt


Type the above into your Bash window and hit enter:


Remember from the previous post that in many cases, when a Bash command executes successfully, we are rewarded with simply a new command prompt. However, we can use the ls command we learned from the last post to examine the contents of our directory:


What do you know? There is is. Now, you could open the new file using Notepad (or the text editor of your choosing), but you won’t see much. We have created an empty text file. To open the file using Notepad from the Bash prompt, simply type:

Open MyNewTextFile.txt in Notepad using Bash:
$ notepad MyNewTextFile.txt


Or, of course, you could open the file the old-fashioned way - by double clicking on it with your mouse!

Using the echo Command to Write Strings as Output

Before we look at using echo to create a new file, we should understand a little about what echo DOES.

The primary design purpose of echo is apparently to write strings to the standard output (usually, the Bash CLI).

The syntax for echo is:

Echo Command Syntax:
$ echo [options] <string>


Lets try that now. Type the following into Bash:

Output a line of Text to the Bash Screen:
$ echo show this line on the screen



We can also tell the echo command to write a line of text to a file, using the following syntax:

Syntax: Append text to the end of a file:
$ echo [options] <Text string> >> <FileName>


By using the >> (double right-hand angle-brackets) operator, we tell Bash to append the text to the end of the file. Type the following into the Bash window and hit enter:

$ echo This line was added to the end of the file >> MyNewTextFile.txt



Now, if we use our $ notepad MyNewTextFile.txt Command, we see the following:


Close that window, and let’s add another line. Type the following and hit enter:

Adding Another Line of Text:

$ echo This is another line of text >> MyNewTextFile.txt


The use $ notepad MyNewTextFile.txt again:

Open-Text-File-After-Another Append-Line

Huh. Looks like it worked, kind of. Apparently, Bash isn’t kidding about appending the new text to the end of the file. Happily, we can use the > (a single right-hand angle bracket) operator to replace the text in the current file and get rid of that mess. Type this and hit enter. Then open the file in Notepad again:

Replace the Text in a File with a New Text String:
$ echo This line replaced the old mess > MyNewTextFile.txt

Your Bash window should look like THIS:


And you should see this in your Notepad window:


Use the Echo Command to Create a New File with Text Content:

Ok, back to the original subject - creating a new text file. We can use echo to create a new file, and include the specified text string as content. In fact, it works the same as when we appended or replaced the text in an existing file, because, lacking an option argument telling it not to, Bash will assume that if the file specified in our echo command does not exist, that we want to create one. Type the following and hit enter:

$ echo This is a new line in a new file >> DifferentTextFile.txt


Then use ls -1 to display the directory contents. This is what your Bash window should look like:


Note the presence of our new file. Let’s open it in Notepad, and see what there is to see:

DifferentTextFile - Notepad

Well, well well. Whadd’ya know!

Bash: Remove Files (rm)

Ok, now lets get rid of our first file. To remove (delete) files using Bash, we use the rm command. The syntax for removing files is as follows;

rm [options] <FileName>


SO now, let’s delete that first file, MyNewTextFile.txt. Type the following, hit enter, then use the ls -1 command to display the directory contents:

rm MyNewTextFile.txt


Your Bash window should look like this:


Remove a Directory and all Contents (rm -rf)

In the previous post, we discussed how to remove an empty directory. But what if we want to remove a direcory and all of its contents? We use the rm command with the -r and -f options:

Syntax for Removing a Directory and All of its Contents:

rm -rf <FolderName>


So now we are going to remove the BashExcercises directory we created at the beginning of this post. Of course, we can’t remove a directory if we are currently IN that directory. So first, let’s return to the directory above (in this case, our home folder) using the cd .. Comand (the cd Command, followed by a single space, followed by two periods in a row. This one means “move up one level”).

Next, type the following into your Bash window, hit enter, and then use the ls -d */ command to view the directories within the current directory (which should be, at this point, your Windows User folder):

$ rm -rf BashExcercises


When you are done, your Bash window should resemble this (note that the directories are organized alphabetically in columns, and the BashExcercises directory is no longer there. Also note that for obvious reasons, your user folder will contain different folders than mine!).


Now, let’s use everything we just learned in this post, plus we’ll add one final tidbit at the end which you may find useful. We’re going to step through this right quick. We will:

  1. Add one more new directory
  2. Add a file containing a line of text to the new directory
  3. Remove the directory and its contents
  4. Have Bash tell us what was removed.
1. Add a New Directory Named OneLastFolder to our current directory:
$ mkdir OneLastFolder


2. Add a New File Named OneLastFile.txt, containing the text “One more text line” to the new folder:
$ echo One more text line >> OneLastFolder/OneMoreFile.txt

Notice in the above, I did not navigate into the new folder to create the new file, but simply used the relative path from my current location.

3. Remove the directory and all its contents, and have Bash tell us what was done:
rm -rfv OneLastFolder

Notice in the above, I added one more optional argument, the -v option (for “verbose”). This tells Bash to print the actions it took to the output window.

When you have done all of that, your window should look like this:


There you have it. You now have the most basic set of tools for using the Bash Command Line Interface. From here, we are ready to examine the basic command line operations required to start using Git to manage our code. We’ll pick that up in the next post in this series.

Additional Resources:


Posted on September 18 2012 04:14 PM by John Atten     

Comments (0)

Basic Git Command Line Reference for Windows Users

Posted on September 8 2012 09:22 AM by John Atten in CodeProject, Education, Git   ||   Comments (0)

gitWhile there are GUI interfaces available for GIT (some good, some bad), familiarity with at least the basics of git’s command line interface can only enhance your ability to use the tool to maximum effectiveness. Since I am relatively new to git and version control in general, I set out to learn the basics of the git command line. In doing so, I found it handy to keep a list of the commonly-used commands nearby so that I didn’t have to keep Googling.

In this post, I am going to cover the very basic set of commands one might require to effectively navigate and maintain your source repo using only the git Bash command line interface. Probably, in creating this post, I will not need to look at this again, as the sheer fact of composing this list and explaining it all will burn these into my brain forever. On the other hand, if I am ever unsure, I will now have a place to come look!

NOTE: The references here are by no means comprehensive. I have included the basic commands required to get started, and the commonly used options for each command. There is a wealth of additional information available on the internet, and I have included some helpful reference links at the end of this post.

To more easily find what you might be looking for, here are some links to specific sections of this post:

Working with the file system

Configuring Git and Creating a Repository:

Staging and Committing Changes

Working with Remote Repositories (like Github)

Undoing Changes and Working With Tags


Git Bash: Syntax Notes

Directory Paths

First off, note that Git Bash is a *nix application (Unix/Linux), and expects inputs according to *nix conventions when it comes to file system navigation. This is important when using Git on a windows system, because we need to mentally map the familiar Windows directory notation to Unix format:

Windows Directory Path <---- Becomes -----> *nix Directory Path
C:\Users\MyUserFolder\   /c/Users/MyUserFolder/


Strings with Spaces

When we are going to provide an input string with no spaces, we need do nothing. However, strings which contain spaces must be enclosed in quotes. Remember this. Personally, I just use quotes around strings in general.

The “Home” Directory

The file system in *nix systems is set up a little differently than in Windows. Git Bash assumes the existence of a “home” directory for each user. In Windows, the default is your personal user folder. This folder is where Git Bash opens by default. Typing only cd after the command prompt will always return you to the root level of the home directory.

Command Syntax Format:

The basic command syntax for a git Bash Command is:

$ CommandName [options] [directory]

In the above, the square brackets denote optional parts of the command. The square brackets themselves are not typed into the command line. Items following a command which are not enclosed in brackets are required.

Cases and Spaces Count

Also note that git Bash is case-sensitive, and spaces count. For Example, the common command to change to another directory is cd. This is NOT the same as CD or Cd.

Optional Input

When portions of a command are optional, we will note this by enclosing them in square braces:

$ Command [options]

In the above, we do type the square brackets.

User Input

For our purposes here, when we are presenting command syntax examples, we will denote user-provided values between angle brackets:

$ Command [options] <SomeUserInput>

In the above, we do type either the square or angle brackets.


Git Bash: Navigating the File System (cd)


cd [options] [<directory>]


Navigate to the Home Directory (Default folder for the current user):
$ cd


Navigate to a specific folder in the file system:
$ cd /c/SomeFolder/SomeOtherFolder/


Navigate to a specific folder in the file system (if there are spaces in the directory path):
$ cd “/c/Some Folder/Some Other Folder/”
Go back to the previous Location:
$ cd -
Move Up One Directory Level:
$ cd ..

In the above, the cd command is followed by a space, then two period with no space between.


Git Bash: Show Directory Contents (ls)


ls [options]

-1 = List 1 item per line
-r = Reverse the sort order
-a  = Show Everything, including hidden items
-d = list only directories
-l = (letter L, lowercase) = Use a long listing format (more info per item, arranged in columns, vertical listing)


List the contents of the current directory (folder):
$ ls

The above will display the contents of the current directory as a horizontal list. Not real convenient.

List the contents of the current directory, one item per line:
$ ls -1

That’s better. Note, however, that we can only differentiate files from subdirectories based upon the file extension.

List only the subdirectories (folders) within the current directory:
$ ls –d */


List everything in long form, vertically:
$ ls –al

The above gives a swath of information. Also, subdirectories are differentiated by the first column (begin with drwxr instead of -rw)

List all contents, including subdirectory contents, single item per line:
$ ls -1 *


Git Bash: Create a New Directory (mkdir)


mkdir [options] <folderName>

-p = Create parent directories as needed
--verbose = Show a message for each new directory created (note the double dash)


Create a folder in the current directory (without spaces in the folder name):
$ mkdir NewFolderName


Create a folder in the current directory (with spaces in the folder name):
$ mkdir “New Folder Name”


Create a folder at the specific directory path:
$ mkdir /c/ExistingParentFolder/NewFolderName


Create a folder at the specific directory path, and create parent directories as needed:
$ mkdir -p /c/NewParentFolder/NewFolderName


Create a folder at the specific directory path, create parent directories as needed, and print a description of what was done in the console window:
$ mkdir -p --verbose /c/NewParentFolder/NewFolderName


Git Bash: Create Files (touch, echo)


touch [options] <FileName>

echo [options] TextString > FileName

(NOTE: FileName can include directory. Default is the current directory).

Create a single (empty) text file in the current directory:
$ touch newFile.txt


Create a single (empty) text file in the specified directory:
$ touch /c/SomeFolder/newFile.txt


Create multiple (empty) text files in the current directory:
$ touch newFile_1.txt newFile_2 . . . newFile_n


Append text to a file. If the file does not exist, one is created:
$ echo “This text is added to the end of the file” >> newFile.txt


Overwrites text in a file. If the file does not exist, one is created:
$ echo “This text replaces existing text in the file” > newFile.txt


Overwrites text in a file at the specified location. If the file does not exist, one is created:
$ echo “This text replaces existing text in the file” > /c/SomeFolder/newFile.txt


Git Bash: Remove Files (rm)


rm [options] -<FileName>


-I (or --interactive) = Prompt before removal

-v (or --verbose) = Explain what is being done

Remove the specified file from the current directory (no spaces):
$ rm -DeleteFileName


Remove the specified file from the current directory (with spaces):
$ rm -“Delete File Name”


Prompt for confirmation before remove the specified file from the current directory (no spaces):
$ rm -i -DeleteFileName


Removes the specified file and reports what was done in the console window:
$ rm -v -DeleteFileName


Git Bash: Remove Directories (rmdir, rm -rf)


rmdir [options] <FolderName>

rm -rf

Removes the specified folder if empty. Operation fails if folder is  not empty:
$ rmdir -DeleteFolderName


Removes the specified folder and all contents:
$ rm -rf -DeleteFileName


Git Bash: Configure Git (git config)


git config --global <“User Name”>

git config --global <UserEmailAddress>

Set the global User.Name value for the current user on the system:
$ git config --global “FirstName LastName”


Set the global User.Email value for the current user on the system:
$ git config --global UserEmailAddress


Show me the current values:

The following return the current values for the and properties respectively and output the values to the console window:

Print the current global User.Name value to the console window:
$ git config --global


Print the current global User.Email value to the console window:
$ git config --global


Git Bash: Initialize a New Git Repo (git init)


git init

Create files required in the current directory to perform version control:
$ git init


Git Bash: Add/Stage for Commit (git add)


git add [options] [<File_1>] [<File_2>] . . . [<File_n>]


-A (or --all) = Add all new or changed files to the staged changes, including removed items (deletions)

-u = Add changes to currently tracked files and removals to the next commit. Does not add new files.

. = Adds new or changed files to the staged changes for the next commit, but does not add removals.

Note that git add -A is semantically equivalent to git add . followed by git add –u

-p = Interactive add. Walks through changes in the working directory and prompts for add

Add all changes in the working directory to the next commit, including new files and deletions:
$ git add -A


Add all changes to tracked files and all new files to the next commit, but do not add file deletions:
$ git add .


adds all changes to tracked files and all file removals to the next commit, but does not add new files:
$ git add -u


Walks through changed files and prompts user for add option. Does not include new files:
$ git add -p


Git Bash: Unstage from Commit (git reset)


git reset HEAD <File_1>

Remove the specified file from the next commit:
$ git reset HEAD FileName


Git Bash: Committing Changes (git commit)


git commit [options] [<File_1>] [<File_2>] . . . [<File_n>] [-m <“Commit Message”>]


-a = Commit all changes to tracked files since last commit

-v = Verbose: include the diffs of committed items in the commit message screen

--amend = Edit the commit message associated with the most recent commit

--amend <File_1> <File_2> . . . <File_n> = redo the previous commit and include changes to specified files

Commits the changes for the specific file(s) and includes the commit message specified:
$ git commit FileName –m “Message Text”

Note that Git requires a commit message. If you do not provide one using the -m option, you will be prompted to do so before the commit is performed.

Commits all files changed since last commit. Does not include new files.
$ git commit –a –m “Message Text”


Adds all changes to the previous commit and overwrites the commit message with the new Message Text. Does not include new files:
$ git commit –a –amend –m “Message Text”


Git Bash: Remote Repositories (git remote)


git remote add <RemoteName> <RemoteURL>

git remote show <RemoteName>

NOTE: As used here, RemoteName represents a local alias (or nickname) for your remote repository. The name of the remote on the server does not necessarily have to be the same as your local alias. 

Add the specified remote repo to your git config file. The remote can then be pushed to/fetched from:
$ git remote add RemoteName https://RemoteName/Proj.git


Print information about the specified remote to the console window:
$ git remote show RemoteName


Git Bash: Branching (git branch)


git branch [options][<BranchName>][<StartPoint>]


-a = List all local and remote branches

-r = List all remote branches

List all local branches:
$ git branch


List all remote branches:
$ git branch -r


List all local and remote branches:
$ git branch -a


Create a new branch starting at the some point in history as the current branch:
$ git branch BranchName

Note that this creates the new branch, but does not “check it out” (make it the current working branch).

Switch from the current branch to the indicated branch:
$ git checkout BranchName


Create a new branch and switch to it from the current branch:
$ git checkout –b NewBranchName StartPoint

Note that StartPoint refers to a revision number (or the first 6 characters of such) or an appropriate tag.



Git Bash: Merging Branches


git merge [<BranchName>][--no-commit]

Merge the specified branch into the current branch and auto-commit the results:
$ git merge BranchName


Merge the specified branch into the current branch and do not commit the results:
$ git merge BranchName --no-commit


Git Bash: Pushing to Remote Repositories (git push)


git push [<RemoteName> <BranchName>]

Update the remote server with commits for all existing branches common to both the local system and the server. Branches on the local system which have never been pushed to the server are not shared.
$ git push


Updates the remote server with commits for the specific branch named. This command is required to push a new branch from the local repo to the server if the new branch does not exist on the server.
$ git push RemoteName BranchName


Git Bash: Fetching from Remote Repositories (git fetch)


git fetch <RemoteName>

Retrieve  any commits from the server that do not already exist locally:
$ git fetch RemoteName

NOTE: git fetch retrieves information from the remote and records it locally as a branch in your current repository. In order to merge the new changes into your local branch, you need to run git fetch followed by git merge. Since there may be more than one branch on the remote repository, it is necessary to specify the branch you wish to merge into your current branch:

Merge syntax for post-fetch merge:

git merge <RemoteName/BranchName>

Merge the newly fetched branch from the remote into your current working branch:
$ git merge RemoteName/BranchName

Using fetch before merging allows you to pull changesets in from the remote, but examine them and/or resolve conflicts before attempting to merge.


Git Bash: Pulling from Remote Repositories (git pull) 


git pull <RemoteName/BranchName>

Fetch changes from the specified branch in the remote, and merge them into the current local branch:
$ git pull RemoteName/BranchName


NOTE: git pull is essentially the same as running git fetch immediately followed by git merge.


Git Bash: Undo (git reset)


git reset [options]


--hard = undo everything since the last commit

--hard ORIG_HEAD = Undo most recent merge and any changes after.

--soft HEAD^ = undo last commit, keep changes staged

Undo everything since the last commit:
$ git reset --hard


Undo most recent successful merge and all changes after:
$ git reset --hard ORIG_HEAD


Undo most recent commit but retain changes in staging area:
$ git reset --soft HEAD^


Git Bash: Tags (git tag)


git tag [options] [<TagName>] [<CommitChecksum>] [<TagMessage?]


-a = Annotated Tag

-m = Annotated Tag Message

List all tags in the current repository:
$ git tag


Create a tag at the current revision:
$ git tag TagName


Create a tag at the commit specified by the partial checksum (six characters is usually plenty):
$ git tag TagName CommitChecksum


Create an annotated tag:
$ git tag -a TagName -m TagMessage


Create an annotated tag at the commit specified by the partial checksum:
$ git tag -a TagName CommitChecksum


Push tags to a remote repository:
$ git push --tags


Print information about a specific tag to the console window:
$ git show TagName


Almost all of the information presented above represents a “toe in the water” sampling designed to get started. There are plenty more commands for use both within Git itself, and from the more general Bash command line. Additionally, most of the commands listed here have more options than I have included. I tried to keep this simple, as a reference for myself, and for whoever else may find it useful to get started with the basics.

Additional Resources


Posted on September 8 2012 09:22 AM by John Atten     

Comments (0)

About the author

My name is John Atten, and my "handle" on many of my online accounts is xivSolutions. I am Fascinated by all things technology and software development. I work mostly with C#, JavaScript/Node, and databases of many flavors. Actively learning always. I dig web development. I am always looking for new information, and value your feedback (especially where I got something wrong!). You can email me at:

johnatten at typecastexception dot com

Web Hosting by