In my last post about Git I went through some of the essential tools you’ll need in order to use Git on Windows. Now that you have Git up and running on your machine, we can start talking about how to actually use it.
Creating A Repository
This is Git 101 stuff, but I I’d be remiss if I didn’t at least briefly mention how you create a Git repository. When you create a Git repository, you’re essentially taking a folder and letting Git treat it like it’s own mini file system. Open a PowerShell prompt, navigate to the root folder of the project that you want to store in Git and run the following command:
Note that the ‘git init’ command is only for creating new Git repositories. You’ll sometimes want to get copies of existing Git repositories, which is done with the ‘git clone’ command. We’ll talk more about that when we talk about using remotes in a future post.
If you followed the instructions in my last post, the Git executable should be in your PATH and you should get a message back indicating that the Git repository was created. You might notice that there is a new folder created when this command completes called “.git”. The .git folder is where Git will keep snapshots representing your changes over time and all of the other metadata that it needs to do its job. There’s only 1 .git folder created per repository and it will always live in the root folder. You can note its existence when it first gets created, but hopefully you’ll never have to do anything to it directly. If you want to make a copy of the repository or move it to a new location, you just need to move or copy the root folder and all of its files and sub-folders (including the .git folder) to a new location.
If you’re using posh-git, you’ll notice that your PowerShell prompt will look different after the init command finishes running. Whenever you’re in a folder or sub-folder of a Git repository the posh-git helpers show you what branch is currently checked out and whether or not you have any pending changes that might need to be committed. Immediately after creating a new Git repo any files not in the .git folder will be counted as pending changes that you’ll want to include in your initial commit. Before making that initial commit you’ll want to create a couple of other files that will help Git correctly manage your project.
Note: as of Visual Studio 2013 you can choose ‘Git’ as your source control provider when creating a new project, and it will automatically init a new Git repo for you and create the files that I’m about to describe below automatically. Personally, I don’t use the Git tools for Visual Studio and I think it’s important to understand how to create a repo manually, so that’s what I’m describing in this post. If you want to just let Visual Studio do everything for you, at least read the following sections to understand why Visual Studio is doing it. If not, go ahead and skip down to the “Initial Commit” section at the end of this post.
If you’re developing on Windows you’re likely using Visual Studio. As you probably know, Visual Studio can add lots of cruft to the folders that contain your project in the form of solution option (.suo) files, compiled assemblies, files created by 3rd party plug-ins (looking at you, ReSharper), and lots of other “meta” files that don’t actually do anything in the application that you’re working on. Most source control systems give you a way to exclude certain files from being tracked and versioned and Git is no exception. To ignore files in Git you add a special text file to the root of your repository named “.gitignore” (note: this is a file with no name and an extension of gitignore; it might seem odd to create a file like this in Windows, but you’ll find that Git make extensive use of dot files like these). The .gitignore file describes files that you want Git to ignore completely. You can find lots of examples online for .gitignore files that are suitable for use with Visual Studio projects. Here’s one that I commonly use:
If you read through that example you’ll get a feel for how to ignore certain types of files using wild cards. The file linked above will work for most Visual Studio projects, but if you have specific files for your project that you want to ignore you can certainly tailor the .gitignore file to your specific needs.
Pretty simple right? Here’s the only thing about the .gitignore file that tripped me up a bit when I first started using Git: you commit the .gitignore to the repository. Meaning you don’t ignore the file that describes what to ignore. I suppose you technically can ignore the .gitignore file, but as soon as I say, “… but I can’t think of any reason why you would” someone will chime in with a “well, actually” and explain the obscure edge case where you might want to. There are exceptions to every rule, but you probably want to just go ahead and commit your .gitignore file so that everyone who works on your project will always automatically ignore the same types of files.
On Line Endings
Line endings is the type of computer problem that you really shouldn’t have to think about, but as a Windows developer using Git you’re you may bump into an issue or two with line endings. In case you are blissfully unaware of what I’m talking about I’ll summarize the crux of the issue really briefly:
In Windows, files containing text (e.g.: plain text files, code files, XML files, etc.) have traditionally used both a Carriage Return (CR) and Line Feed (LF) character to denote the end of one line and the beginning of the next. Other operating systems, however, use just the Line Feed (LF) character. These days most programs that let you view and edit text (including Visual Studio) can deal with both types of files. That said, Visual Studio sometimes complains if you have a file where both styles are mixed. Again: this is a stupid problem, but having inconsistent line endings in the files that make up your project isn’t a good idea.
Fortunately Git has ways of helping us deal with potential line ending problems. I’d write in detail about them here, but fortunately for me one of the smart folks at GitHub already has. This post is the best explanation of how Git can help you deal with line endings that I’ve found; you should read it right now: Mind the End of Your Line.
If you go looking for opinions on how to deal with line endings in Git you’ll find more than a little disagreement. A lot of folks think that you should tell Git to store line endings consistently (usually as LF) in the repository but convert to a platform-specific line ending (e.g. CRLF if you’re on Windows) when you get a file out of the repository to work on. Other folks think that the source control system shouldn’t be modifying the contents of files as they move in and out of the repository at all. Every time is different, but I’ve always let Git convert my line endings for me and it hasn’t ever really caused a problem for me or anyone else I’ve worked with. As always, Your Mileage May Vary(tm). If you want my recommendation, do this:
- Turn the autocrlf Git configuration option on (run: “git config –global core.autocrlf true”). Most applications that install Git on Windows will automatically turn this on for you, so you probably already have it on.
- Use a sensible .gitattributes file for your project. The one that is used as an example in the “Mind The End Of Your Line” post is probably suitable for most .NET projects (and you can always tweak it for your specific needs).
- If you want to know more about .gitattributes and how to set it up, check out this “Customizing Git – Git Attributes” section of the Pro Git e-book.
Now that you have your .gitignore and .gitattributes in place, it’s time to create the initial commit for your Git repository. You can use a GUI tool for this, or you can just run the following from the command line to automatically stage and commit all files that haven’t been ignored:
git commit -a -m "Initial commit"
Note the “-a” argument lets us bypass adding/staging all of the files being committing, and the “-m” argument lets us specify a commit message.
In the next post in this series, I’ll talk about communicating with remote repositories.