The argument of this post can be relevant to people using Subversion and willing to give a try to Git.
In this article I will try to give a quick way to get started with Git by learning to work with it in a Windows environment and from inside Visual Studio 2010.
After a quick review of some GUI clients available for Windows I realized that all of them are still immature.
I chose the most promising ones: Git Extensions which is a Windows Explorer integration and Visual Studio plug-in, paired with: Git Source Control Provider which is a Visual Studio integration.
If you download and install the latest version of Git Extensions you don’t need to install Git separately. You got it installed together with Git Extensions (the version I’m using for this article is Git Extensions 2.43).
When you run the installer, after choosing the user for which to install, you will be prompted to check the additional software you want to install.
Given that we still didn’t install Git for Windows (Msysgit), check it. Check also KDiff3 which is the default Diff/Merge tool used by Git.
In the next screen leave the default installation path. In the following screen: Custom Setup, you can customize the installation.
You can check the Visual Studio integration for your version of Visual Studio. Mine is VS2010 as in the screenshot:
In the next screen leave Putty as the selected SSH Client (I will explain later why you need it).
You’re now ready to install.
During the installation you will be prompted to accept the KDiff3 license and to customize the KDiff3 installation if you mind.
I deselected the integration with TortoiseSvn, for example, because I want TortoiseSvn to keep using TortoiseMerge. Click next few times and the KDiff3 installation will start.
After completing KDiff3 installation you will be alerted that the Git Setup is starting (in my case is Git version 1.8.0):
I just clicked next at all the screens until the one titled: Adjusting your PATH Environment.
Here and in the following screen I followed Igor Zelmanovich’s instructions (see his blog post) and I chose the following options:
Now Git for Windows will be installed and after finishing this part of the installation the Git Extensions main installer will end up Git Extensions installation and will prompt you with the ending message.
2. A Little bit of Git Background
For a thorough description of how Git manages commits I suggest you the free ebook: Git Pro.
I’m a newbie to Git but I will try to explain you the way in which Git works as far as my omprehension
allows me to explain.
Important Note for Subversion users: always remember that in the IT world you’re not a Guru if you don’t use the same words someone else is using elsewhere but giving them a different meaning.
Git is no exception to this as all the other CVS systems. So remember that words like Checkout and Commit represent quite different things than they do in Subversion! (thought similar enough to get you confused)
Let’s start with Repository creation:
First of all suppose you already have a Git repository to start from.
The trunk branch is called master in the Git world.
The first thing to do in the Svn world is to Checkout a Working Copy but here in the Git world you won’t get only a Working Copy as you’re used to see it. You will get a local copy of the repository itself too.
This is the reason why in Git the word for this first operation is: to Clone the central repository (while Checkout is reserved for a different thing).
When you Clone an existing repository you will get a copy of the repository, together with your Working Copy containing the current version of the master branch.
You can now start working on the master branch and everytime you will commit your changes will be sent to your local repository. You will not be sending your changes back to the original repository.
When you will feel ready to send your changes to the central repository you can Push your local master branch back to the origin/master branch on the central repository.
If development proceeded in the central repository and it turns out that someone else Pushed its changes in the meanwhile, Git will block your Push inviting you to merge locally your master branch with the updated version of the central repository’s branch.
You will have to Fetch remote changes and, in Git language this means invoking a Pull of the remote branch.
Your repository will contain now an updated version of the remote (origin) master branch and your modified version of an older master branch. You will have to merge in your local machine the updated remote master with your locally modified master and resolve any conflicts, if needed.
If your changes still work with the newer version of master and everything works locally, you will be allowed to Push your changes.
In order to be able to Pull you need to make sure there are no uncommitted changes in your local repository.
The added value of Git comes with the recomendation about how to work with it: we are strongly suggested to always create a new branch and work on it, instead of working on the master branch:
- you clone a central repository
- you want to work on a bug fix
- you create a new branch locally named: bugfix
- you switch your working copy to that branch (Checkout to that branch in Git words)
- you work on that branch and commit your changes
- you suspend your work because you want to work on a new feature
- you create a new branch locally named: newfeature
- you switch your working copy to that branch (Checkout to that branch in the Git world)
- you work on that branch and commit your changes
You have easily worked on the same project keeping somewhat separated your ‘workitems’.
Git has a very strong support for branching and merging branches in order to allow you to be confident that creating, merging and deleting branches is a safe, and often light, operation.
Back to our example. In your repository you now have:
- a copy of the origin/master you obtained when cloning
- a local master aligned with the origin/master (a pointer to the same commit)
- a local bugfix branch
- a local newfeature branch
If you want to send your bug fix to the project owner you will:
- fetch the updated version of origin/master
- merge it locally to your bugfix branch
- check that everything is ok
- push your bugfix branch back to the central repository
- ask the project owner to pull your branch and to merge it with the origin/master (send a Pull Request in Git language)
If you are authorized to push to the origin/master you can replace point 5 with the following:
- merge locally your bugfix branch to your master branch
- push your changes to the central repository
If you didn’t merged locally with your master branch you have one more advantage: you now have
- an up-to-date copy of the origin/master
- a local master that you can merge with the origin/master to get them aligned
- a local bugfix branch (merged with the updated master and then pushed)
- a local newfeature branch
You can now merge locally master to your newfeature branch, check that everything is ok
and then push this other branch.
You were able to check your branches separately with the updated origin/master and to push them separately.
If any of the two will be refused you could discard it or work more on it while keeping the local master aligned with the origin/master.
If you don’t have write permission on the central repository, as is often the case for projects hosted on Github, you can Fork the central repository, Push to the Fork and send a Pull Request to the administrators.
Forking means creating another central repository by cloning the original one but with write permissions for the user who is forking.
You can than add this new central repository to the Remotes linked to you local repository and Push your branch to the Forked central repository.
Sending a Pull Request means communicating to the administrators that you created a Fork and added a Branch to that Fork, containing some interesting changes. The administrator could than add your Fork to the remotes of their local repository, Fetch your changes, Merge them in a local Topic Branch and integrate with Master if they find it useful and stable.
3. First run with Git Extensions
Now you can run Git Extensions, choose your preferred language and wait for initialization.
You will be prompted with a screen with the settings checklist:
Here you will see a warning saying that you need to configure a username and email address.
Click: Repair and add the information required. Click: Ok and the Git Extensions main window will open:
We can now try to create a new Git Repository by clicking the link: Create new repository.
We will be asked to specify the folder in which the repository will be created and the type of repository we want.
When you create a repository you can create it bare (Central Repository) or you can have a working copy created as well (Personal Repository).
If you select Personal Repository and click Initialize you will obtain a working directory containing the local copy of an empty repository and you can start working in it. You will be able to Clone that repository even if it is a personal one.
If you choose Central Repository you will get a folder containing an empty repository but without a working directory associated. You will need to Clone it to start working with it.
Let’s choose the second option and we will be redirected to the following screen:
This repository represent your central repository: the origin from which everyone should clone his local repository and to which Push changes.
If we want to start working with it, our next step will be to Clone it.
From the Commands menu we can choose: Clone repository and we will be prompted with the following screen:
In this window we cannot select the branch to Clone because an empty central repository has not even a Master branch. The Master branch will be created the first time we will Push to it from a Personal repository.
Fill the target folder for the Personal repository as shown in the above picture and click Clone, then click Ok and, when prompted to choose if you want to open the cloned repository, choose: yes.
You will be redirected back to the main page but you will still be on the original repository on the master branch.
In the top bar (under the bar with the menus) you can see the path to the current repository. Click the dropdown arrow and choose the cloned repository: GitFirstClone.
If you choose: Remotes –> Manage remote repositories you will see the Central repository marked as origin of the current one.
If we go back to the central repository in Git Extensions we will find no remote configured because a Central repository is supposed to be created bare and not Cloned.
Go to the folder in which the repository has been created (File –> File Explorer) and create a new file: First.txt
In the Git Extensions window the Commit button that used to be green in the above screenshot is now red with: (1) aside. Click Commit and a new window will open to manage the commit:
If you click the Commit button you will be prompted with the following message:
The explanation is easy: I still didn’t talk about the staging area in Git.
When you add, modify or delete something in your working directory you can decide to commit your changes locally but in order to do it you have to move the desired files in an area called: staging area.
You can Commit only if the staging area is not empty and you will Commit only the changes already staged.
So let’s move our file in the staging area, provide a Commit message and then commit.
You will be redirected to the main page, showing you details about the last commit happened in the current freshly created branch (master branch).
The staging area is much more than this: when you stage a file you move to the staging area the current version of that file, not a pointer to it.
So you can modify the file and you can decide to immediately stage your change to be sure that when you will commit, your change on this file will be committed. You can than go on adding text to the file but if you don’t stage the file any more, when eventually you will commit, only the staged changes will be committed.
Modify your file by writing: ‘first change’ in the first row, stage it and then add a second row: ‘second change’.
Now our central repository is still empty because we didn’t Push anything.
If a second user clones our Personal repository, instead, he will get the file: ‘First.txt’ but with only ‘first change’ written in it.
Go to: Commands –> Clone repository
Fill the fields in the new window as in the following screenshot:
This time we can specify the master branch because GitFirstClone contains one.
Click Clone, then click Ok and, when prompted to choose if you want to open the cloned repository,
You will be redirected back to the main page but you will still be on the GitFirstClone repository on the master branch.
Select the GitSecondClone repository.
If you now go to the folder of the GitSecondClone working directory and open: ‘First.txt’, you will see only the words: ‘first change’.
Only such words had been staged and then committed, as expected.
Let’s now delete GitSecondClone and recreate it by Cloning the central repository.
If you now go back to GitFirstClone In Git Extensions and select: Commands –> Push you will be prompted with the following screen:
showing you that you will push to the origin repository of GitFirstClone (you can verify that it is
the Central repository by clicking: Manage remotes).
The only branch we can push is: master because we still didn’t create other branches (the Head option represents the master branch as well).
You can click:strong>Push and you will be asked if you want to create a new master branch in the remote repository.
Click yes and, if you will go to the Central repository, you will eventually see the master branch freshly created during the push operation.
We can now go to GitSecondClone which is still empty and fetch from its remote origin, that is the Central repository.
Commands –> Pull will accomplish this prompting you with the following screen:
You can not specify the origin branch to fetch because only the master branch (default) is available.
Clicking Pull will get the content pushed from the GitFirstClone to the Central repo. Going to the GitSecondClone folder you will see the First.txt file with the expected content.
Let’s try to create a new branch and work on it.
Load the GitFirstClone project and select: Commands –> Create branch
In the window that pops up:
choose a name for your local branch and click: Create branch.
You will be redirected to the main window, where you can see the graph of your working directory, showing that your local folder contains a master and a feature1 branch. Both are aligned and both of them are aligned to the origin/master branch as Git knows it from the last Pull operation.
If you didn’t clear the checkbox in the previous window, you are now working on your new branch.
Let’s modify the file: First.txt and add a new one: Second.txt.
Stage both files and then commit. You will see that your feature1 branch is one step forward to your master branch.
You can now Merge the feature1 branch into your master branch and then push it to the Central repository.
Change your working folder to be: master then select: Commands –> Merge branches
In the new window select feature1 as the branch to Merge with:
Now your master branch contains the changes you did in your: eature1 branch.
If you look at the graph in the main window you will se your local branches aligned with each other while the origin/master is one commit back.
Now you’re ready to push your changes to the origin/master in the Central repository.
Select: Commands –> Push and leave all the options as preselected (Push local master branch to remote master branch)
In the main window you will see now that origin/master is aligned with your local master branch.
You can now give a try to the various workflow situations described in the previous paragraph: 2. A Little bit of Git Background.
4. First run with Visual Studio 2010
Let’s now try to use Git from inside Visual Studio 2010.
Open an existing solution or create a new one with Visual Studio and you will find a new menu item in the menu bar: Git.
From there you can access all the main functionalities of Git exposed via Git Extensions windows.
You can Initialize a New Repository while having selected the solution in solution explorer and the Git Extensions window will popup correctly filled.
After that, you will be able to use the usual Git Extensions window for staging and committing changes.
Everything you can do so far from inside Visual Studio 2010 is simply:
- invoking Git Extensions as an external tool via the Git menu,
- viewing file history,
- revert changes when right clicking a versioned file in solution explorer.
We want a little bit more integration with Solution Explorer, so we will download and install: Git Source Control Provider.
You can also install it from Tools –> Extension Manager in the Visual Studio menu.
Once installed you should set it as the Source Control Provider from Tools –> Options, selecting: Source Control in the left tree and choosing: Git Source Control Provider, as in the following image:
In the subsection: Git Source Control Provider Options specify: ‘C:/Program Files/KDiff3/kdiff3.exe’ as diff tool, instead of the default: diffmerge.exe
You will find a complete Git Source Control Provider Options tutorial (Installation and usage) at:
If you want to give it a try before looking at the tutorial you can follow the steps below:
Create a new solution with a class library project, say: GitSolution.sln with GitProject.csproj.
Right-click on the Project and click on the Create Git Repository menu item:
After a while a Personal repository will be created in your solution folder and the files in solution explorer will be marked as new.
You should see the bottom tabbed window: Git Pending Changes (master). If you don’t, right-click anywhere in
Solution Explorer and select: Git Pending Changes.
The bottom window will show up:
You can see that a .gitignore file has been automatically created. A .gitignore file is a file containing the file types to be excluded from versioning (e.g.: .dll, .exe, .suo, etc).
If we select all the items in the pending changes window, provide a message and click commit, everything will be committed and the yellow plus signs will become lock icons.
This is the standard visualization. You can change it in Tools –> Options.
In the section: Git Source Control Provider Options you can specify: Use TortoiseGit style icon set (you don’t need to install TortoiseGit for this) and the lock icons will become green icons.
If you modify a file, the icon will turn red and the file will appear again in the Git Pending Changes window.
At the moment, we’re working with a Personal Repository. If we want to create a Central Repository we need to do it via Git Extensions.
You can select from the menu bar: Git –> Initialize new repository and a window will popup.
This is the same window we saw in the previous paragraph.
Select the target folder, specify: Central Repository and click: Initialize.
Now you can Push to the GitCentral repository from Visual Studio by right-clicking the solution and choosing:
Git(master) –> Push
The Push window we saw in the previous paragraph will open. Specify the folder containing the freshly created Central repository and click: Push.
Next time you will have to select the Url again. Or you can click on: Manage remotes and configure the central repository in the following window:
Specify: origin as the Name and browse to specify the Url to the central repository. Then click the Save button on the bottom left. Click: Yes when prompted for confirmation and a new Remote will be configured for you working folder.
From now on you can Push by simply selecting: Git(master) –> Push and specify origin as the target remote (if not selected by default).
Suppose you are a second developer and you want to Clone from GitCentral.
Open Visual Studio and, from the menu bar, select: Git –> Clone repository
The Git Extensions’ Clone window will open. Browse to GitCentral as the repository to clone and specify the path to the new Personal repository (say: C:\develop\GitClonedSolution). Click the Clone button.
The specified folder now is the root of the Visual Studio solution cloned from the central repository but it has not been loaded into Visual Studio. You have to open it manually.
You can now work on it. You can create local ‘topic’ branches for instance.
You can select: Create branch from the Git menu command or Create Branch from the Git Extensions menu command in the Pending Changes window.
In both cases you will be prompted with the Git Extensions’ Create branch window we saw earlier.
If you specify the name of your new branch (say: feature1) and click: Create branch, your Solution Explorer window, in Visual Studio, will have its title changed from: Solution explorer(master) to: Solution explorer(feature1).
You can work on your solution and Commit but until you won’t Merge to the master branch and Push to the central repository, anyone else pulling from the central repository won’t get any change.
If you now right click the solution and select: Git(feature1) –> Checkout Branch, then select the master branch you will have the master version of the solution, loaded in Visual Studio.
The Merge option specified for Local changes by default, seems to be ignored.
Now you can right click and choose: Git(master) –> Merge and select the feature1 branch as the branch to merge with.
You can now right click and choose: Git(master) –> Push and send the changes to the central repository.
From another instance of Visual Studio you can now open the solution: GitSolution, right click and choose: Git(master) –> Pull and get the changes from the central repository.
I suggest to have a look at Git history by selecting: Git history in the Pending changes window.
You will get a visual representation of the commit history for the project.
Each commit is a big square. Colored balloons indicate the current position of the various branches known to the working directory (personal repository).
If you select a square you will be redirected to a window showing the details of the selected commit.
For further reference you can visit the following good posts, from which I started my journey into Git: