Skip to content

2013

Getting started with Git and BitBucket on Windows

This post describes setting up Git on Windows and using a private remote Git repository hosted on BitBucket.org. Here it goes:

1) Start by downloading Git fromthe msysgit site. At the time of writing the latest installer was Git-1.8.1.2-preview20130201.exe. For some unknown reason the installers are labeled “preview” which normally suggests unfinished product, but the versions are actually fully functional.

After downloading, run the installer and follow the steps. You may use the default options on each screen, but since we are going to try TortoiseGit later, on the first screen select “Simple context menu (Registry based)” and check only “Git Bash Here”. That will keep to your Windows Explorer context menu less cluttered.

2) Install TortoiseGit. At the time of this writing the latest version was 1.8.1. There is nothing special about installing TortoiseGit.

To verify the TortoiseGit installer integrated with your msysgit installation: right click anywhere in Windows Explorer and select TorstoiseGit > Settings from the context menu, then make sure you have the correct paths for Git.exe under the General section and the ssh client under the Network section.

git-tortoisegit-settings-general git-tortoisegit-settings-network

3) Install the Credential Caching Git extension. We will be using Git via https:// instead of ssh and that extension caches the username and password, so we do not have to type them all the time. Download git-credential-winstore and GitPad for Windows 8 (.NET 4.0 required), unzip,copy git-credential-winstore.exe to the Git bin directory and run it. By default Git is installed in C:\Program Files (x86)\Git\bin on 64 Bit systems. Open your global .gitconfig file. The global .gitconfig file is in your home directory which on Windows Vista and above should be under C:\Users\<yourname>. Verify the you have this line in .gitconfig*:

[credential]
helper = !~/AppData/Roaming/GitCredStore/git-credential-winstore

4) Optionally you may want to change the default text editor that Git uses, e.g. you might need that for commit messages. The default editor in msysgit is Unix VIM. You can change that to Notepad with GitPad – a small utility found in the credential caching extension zip. Simply copy GitPad.exe inC:\Program Files (x86)\Git\bin and run it.

5) Create an empty Git repository onBitbucket.org – that will be your shared repository. If you are new to BitBucket you can check this shorttutorialon how to create a BitBucket account and a Git repo- the process is rather straightforward. For this demo create a repo and name it SandboxGit. Please note that BitBucket will create a bare repository. A bare repository is one without branches.

create-a-repository-bitbucket-sandbox

6) We are now ready to start playing with the SandboxGit repo. If you are new to Git, it is better to start in Git Bash at the beginning just to get a feeling of Git. Knowing Git command line will help you understand what TortoiseGit or any other GUI tool does later, because in almost all cases, all the GUI tools generate and execute Git commands for you.

Configure default name and email for commits

In Windows Explorer, go to a place where you want to put your working directory, right click and selectGit Bash Herefrom the menu.

In Git Bash prompt enter:

git config --global user.name "user"
git config --global user.email "user@domain.com"

After the changes, C:\Users\<yourname>\.gitconfig should have the user configuration in it:

[credential]
helper = !~/AppData/Roaming/GitCredStore/git-credential-winstore
[user]
name = user
email = user@domain.com

Also we can get the same result with the git config command:

git config --global -l \
credential.helper=!~/AppData/Roaming/GitCredStore/git-credential-winstore \
user.name=user \
user.email=user@domain.com
Configure / disable line ending conversion
git config --global core.autocrlf false

Without that we will get CR/LF conversion warning on each commit, e.g. something like this will be shown for each new line in your source:

warning: LF will be replaced by CRLF in HelloWorld.cpp.
The file will have its original line endings in your working directory.

Modern development tools support both CR/LF and LF line endings, so we do not need Git to do line ending conversion.

Clone the remote repository
git clone https://user@bitbucket.org/primosoftware/sandboxgit.git ./SandboxGit
Cloning into './SandboxGit'...
warning: You appear to have cloned an empty repository.

The first time you do this Git will ask for a BitBucket.org password. After that it will remember the password, because of the credentials caching extension thatwe installed in step 3.

Check the remote configuration

``` bash cd ./SandboxGit git remote show origin

``` bash
git remote show origin
* remote origin
Fetch URL: https://user@bitbucket.org/primosoftware/sandboxgit.git
Push URL: https://user@bitbucket.org/primosoftware/sandboxgit.git
HEAD branch: (unknown)
Local branch configured for 'git pull':
master merges with remote master

Basically we have:

  • An origin alias that points to a remote repo at https://user@nullbitbucket.org/primosoftware/sandboxgit.git
  • A local branch master that will merge with the remote branch master. However, the remote master branch does not exist yet. It will be created when we do our first commit and push.
  • A remote HEAD branch that is unknown.

Think of HEAD as a symlink/shortcut to a branch. The HEADis unknown because there are no branches in the remote repository yet. Normally HEAD points to themasterbranch.

Add a file and commit

In the SandboxGit folder create a fileHelloWorld.cppwith some code in it. For example:

#include <iostream>
using namespace std;
void main()
{
    cout << "Hello World!" << endl;   
    cout << "Welcome to Git" << endl; 
}

In Git Bash do git add HelloWorld.cpp:

git add HelloWorld.cpp
... and git commit – enter “Initial commit.” when Git asks for a commit message.

git commit .
[master (root-commit) 8ed71ed] Initial commit.
1 file changed, 7 insertions(+)
create mode 100644 HelloWorld.cpp

The commit is local. Up to this point we have done local changes only. The remote repository on BitBucket.org is still untouched.

tortoisegit-git-sandboxgit-empty-bitbucket

In order for others to see the changes we have to push the changes to the remote location. That is done with thegit push command.

Configure default “push” style

Git pushcan work in one of two ways:

  • matching: pushes all local branches to remote branches with the same name. This may lead to unwanted remote branches created by accident.
  • simple: pushes only the current local branch to its remote brother which is usually a remote branch with the same name. This is a more intuitive behavior.

We will use the simple push:

git config --global push.default simple
Push to the remote repository
git push
Counting objects: 3, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 322 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
remote: bb/acl: user is allowed. accepted payload.
To https://user@bitbucket.org/primosoftware/sandboxgit.git
    * [new branch]      master -> master

Verify that now we have a remote branch called master:

``` bash git remote show origin * remote origin Fetch URL: https://user@bitbucket.org/primosoftware/sandboxgit.git Push URL: https://user@bitbucket.org/primosoftware/sandboxgit.git HEAD branch: master Remote branch: master tracked Local branch configured for 'git pull': master merges with remote master Local ref configured for 'git push': master pushes to master (up to date)

We are done.

#### Configure default name and email for commits

Right click anywhere in Windows Explorer and select **TorstoiseGit > Settings** from the context menu, then enter your name and email on under the **Git** section.

![tortoisegit-git-settings-config-name-email](../assets/images/getting-started-with-git-and-bitbucket-on-windows/tortoisegit-git-settings-config-name-email.png) 

Click *Edit global .gitconfig*. Verify that the *.gitconfig* file now contains the user configuration:

 ``` ini
[credential]
helper = !~/AppData/Roaming/GitCredStore/git-credential-winstore

[user]
name = user
email = user@domain.com

Configure / disable line ending conversion

Again in the TorstoiseGit > Settings > Git section, in the "Auto CrLf convert" group, uncheck the AutoCrlf box.

Without that we will get CR/LF conversion warning on each commit, e.g. something like this will be shown for each new line in your source code:

warning: LF will be replaced by CRLF in HelloWorld.cpp.
The file will have its original line endings in your working directory.

Modern development tools support both CR/LF and LF line endings, so we do not need Git to do line ending conversion.

Clone the remote repository

In Windows Explorer, go to a place where you want to put your working directory, right click and select Git Clone from the menu.

tortoisegit-git-clone

tortoisegit-git-clone-finished

Check the remote configuration

Right click on the SandboxGit folder in Windows Explorer and select TorstoiseGit > Settings from the context menu, then go to the Git > Remote section. Verify the remote url to which the origin alias points.

tortoisegit-git-settings-config-remote

Add a file and commit

In the SandboxGit folder create a fileHelloWorld.cppwith some code in it. For example:

#include <iostream>
using namespace std;
void main()
{
    cout << "Hello World!" << endl;   
    cout << "Welcome to Git" << endl; 
}

Right click on the HelloWorld.cpp file and select TortoiseGit > Add. Check the HelloWorld.cpp file and click OK.

tortoisegit-git-add-file

Right click on the HelloWorld.cpp file again and select Git Commit -> Master. Enter “Initial commit.” for a message. Check the HelloWorld.cpp file and click OK.

tortoisegit-git-commit-file

tortoisegit-git-commit-file-done

The commit is local. Up to this point we have done local changes only. The remote repository on BitBucket.org is still untouched.

tortoisegit-git-sandboxgit-empty-bitbucket

Push to the remote repository

Right click on theSandboxGitfolder in Windows Explorer and select TorstoiseGit > Push from the context menu. Click OK.

tortoisegit-git-sandboxgit-push

tortoisegit-git-sandboxgit-push-done

We are done.

Hg subrepositories: a how-to guide for the “svn:externals” junkie (Part 3)

This post summarizes the Mercurial subrepository vs the Subversion externals experience. This is the third and last post of a multi-part article about Mercurial subrepositories. Please make sure you read Part 1 and Part 2 before reading this post.

In a few words, Mercurial subrepositories are very similar to Subversion “svn:externals” and can be used pretty much the same way. However, there are some differences in the workflow, because of the distributed nature of Mercurial. Here are the main differences from Subversion:

  • You always work in a copy / clone of a remote shared repository.
  • You may commit changes multiple times, but those changes are not visible to others unless you push to the remote shared repository.
  • A commit + push in a subrepository is treated as a local change in the top-level root repository. To make the root change permanent, you have to do a commit + push of the root repository as well.
  • A pull from a remote repository just downloads the latest available changes. In order to apply/merge the changes, you have to manually update your working copy.

On good thing about the pull+update workflow is that, it guards against accidentally losing local changes and allows you to do code merges at your convenience.You can also revert an update and continue in your local copy when an update breaks a lot of code and requires hard manual merge labor. You can update your working copy again later, when you are ready for the code merge.

Hg subrepositories: a how-to guide for the “svn:externals” junkie (Part 2)

This is the second post of a multi-part article about Mercurial subrepositories. Please make sure you read Part 1 before reading this post.

In Part 1 of this series we created a Mercurial container SandboxRootHgrepository and Mercurial repositories for the main project -SandboxHg,and its two depencies – SandboxDep1Hg andSandboxDep2Hg. Then we added the main project and dependency projects as subrepositories to SandboxRootHg.

In this post we will go through a Change / Push and Pull / Update cycle for the subrepositories. If you followed the steps in Part 1 you will end up with a SandboxRootHgstructure similar to the one shown on this screenshot:

sandboxroothg-tortoisehg-workbench-15

Notice the .hgsubstate file. Mercurial added this file to track the subrepository revisions. We will get back to examine this file when we make changes to the projects and we synchronize those changes with the remote shared repository.

To simulate a two machine setup I simply cloned the SandboxRootHgshared remote repository to two separate folders named Work and Home respectively. After that I created two groups in TortoiseHg Workbench registry and rearranged the groups and the repositories to reflect my new directory structure. Here is another screenshot:

sandboxroothg-tortoisehg-workbench-16

We are now ready do do some testing.

Go to the Home folder and add a new file TestFile-1.txt to the SandboxRootHg/SandboxHg folder, right click on the new file and select TortoiseHg/Add Files from the menu, then do Hg Commit. So far the changes have been committed to your local repository clone. You still have to Push the changes to remote shared repository. You can do that in the Synchronize view ofthe TortoiseHg Workbench.

sandboxhg-tortoisehg-workbench-17

Now go to the Work folder,right click onthe SandboxRootHg folder and select Hg Workbench from the menu. Switch to Synchronize view and pull the changes from the remote repository. Hmm.. Nothing came in the Work/SandboxRootHg/SandboxHg folder. We should have received a change set with the TestFile-1.txt. What happened? We added TestFile-1.txt in Home/SandboxRootHg/SandboxHg, committed and pushed the change to the remote server. However we forgot to commit and push the change in the container repository: Home/SandboxRootHg. Right click on Home/SandboxRootHg and select Hg Commit from the menu.

sandboxhg-tortoisehg-commit-18

If you open the .hgsubstate file under the Home/SandboxRootHg folder you will see that after the commit the Mercurial updated the revision id of the SandBoxHg project. The .hgsubstate contents changed from this:

0000000000000000000000000000000000000000 SandboxDep1Hg
0000000000000000000000000000000000000000 SandboxDep2Hg
0000000000000000000000000000000000000000 SandboxHg

to this:

0000000000000000000000000000000000000000 SandboxDep1Hg
0000000000000000000000000000000000000000 SandboxDep2Hg
4090583f58e67f599b5141ed2551be3eb4fe5c8c SandboxHg

Now all we have to do is Push the Home/SandboxRootHg changes to the remote shared repository.

Go again to the Work folder,right click on SandboxRootHg and select Hg Workbench from the menu. Switch to the Synchronize view and pull the changes from the remote repository. This is how my Hg Workbench looks like after the update:

sandboxroothg-tortoisehg-workbench-19

Notice on the screenshot above that our working copy still does not have the latest code in it. TortoiseHg makes alerts us by displaying the “Not a head revision!” message in red. One of the differences between Mercurial and Subversion is that in Mercurial you have a two-step code update. Basically the Hg/Pull command only downloads the latest change sets from a remote shared repository. After you pull the changes you still have to apply them by issuing an Hg/Update command.

Go to the Work folder, right click on the SandboxRootHg folder, and select TortoiseHg > Update from the menu. This updates our working copy with the changes we downloaded when did Hg/Pull.

sandboxroothg-tortoisehg-workbench-21

If you check the Work/SandboxRootHg/SandboxHg folder you will see that the TestFile-1.txt file is now there as it should be.

Continue to Hg subrepositories: a how-to guide for the “svn:externals” junkie (Part 3)

Hg subrepositories: a how-to guide for the “svn:externals” junkie (Part 1)

This is the first post from a multi-part article about using Mercurial subrepositories when you are switching from Subversion to Mercurial and you heavily used Subversion subrepositories configured via the svn:externals property.

Often a common scenario in software development is to have a main project that depends on other projects. Here is an example of how the Subversion “trunk” for such projects might look like:

``` text svn://svnserver/SandboxSvn trunk SandboxSvn (main source code) SanboxDep1Svn (svn:externals link from svn://svnserver/SandboxDep1Svn/trunk) SanboxDep2Svn (svn:externals link from svn://svnserver/SandboxDep2Svn/trunk)

Basically we have a repository at *svn://svnserver/SandboxSvn* that includes the main project called *SandboxSvn* and two projects* SandboxDep1Svn* and *SandboxDep2Svn* on which *SandboxSvn* depends. The dependency projects are linked from two separate Subversion repositories, hosted at *svn://svnserver/SandboxDep1Svn/trunk* and *svn://svnserver/SandboxDep2Svn/trunk* respectively.

You can create a similar structure in Mercurial by using the Mercurial subrepositories. In the example below, I use BitBucket, so I can test my setup later, but the same steps should be valid for any other shared Mercurial setup. For more information on how to use BitBucket, see the [BitBucket 101](https://confluence.atlassian.com/display/BITBUCKET/Bitbucket+101 "BitBucket 101") wiki.

Steps to setup a main project with two dependencies in Mercurial:

1) Create a repository called SandboxRootHg. This will be a containerrepository for both the main project and the dependencies. I set that up at https://bitbucket.org/your-team-name/SandboxRootHg.

2) Create a repository for your main project, e.g. SandboxHg at *https://bitbucket.org/your-team-name/SandboxHg*.

3) Create a repository for each of the dependencies:

- SandboxDep1Hg at *https://bitbucket.org/your-team-name/SandboxDep1Hg*
- SandboxDep2Hg at *https://bitbucket.org/your-team-name/sandboxDep1Hg*

4) Setup the three dependencies in the container project.

You first have to clone the container repository locally to your machine. In our case the containeris *SandboxRootHg*, so I cloned that in a new*SandboxRootHg* folder. In the *SandboxRootHg* folder create a *.hgsub* file(note the dot in the*.hgsub*name), and add the *SandboxHg*, *SandboxDep1Hg* and *SandboxDep2Hg* projects to in the *.hgsub* file. Your final *.hgsub* will have three lines in it and will look similar to this:

``` text 
SandboxHg = https://bitbucket.org/your-team-name/SandboxHg
SandboxDep1Hg = https://bitbucket.org/your-team-name/SandboxDep1Hg
SandboxDep2Hg = https://bitbucket.org/your-team-name/SandboxDep2Hg

5) In the SandboxRootHg folder, do a Hg/Add to add the .hgsub file to Mercurial, then Hg/Commit. And last, do not forget to do a Hg/Push to update the remote shared repository with your changes.

Continue to Hg subrepositories: a how-to guide for the “svn:externals” junkie (Part 2).