Close

Git - Remote repository basics

[Updated: Feb 25, 2019, Created: Feb 2, 2019]

The remote Git repositories host our projects through the Internet or network.

The main purpose of a remote repository is to place the repository to a central location so that it can be accessed by multiple developers.

A remote repository can be accessed via http, ssh or even local (file-system) protocols.

In this tutorial we will keep the things simple and see how to push, clone and pull projects over the local protocol (local file system). Let's see that step by step with an example.

Creating and Adding a project to Git

Let's start git bash from which we will create a project under a directory 'my-project' and will add that to Git.

Joe@jpc MINGW64 /c/git-local-repository-example
$ dir

Joe@jpc MINGW64 /c/git-local-repository-example
$ mkdir my-project

Joe@jpc MINGW64 /c/git-local-repository-example
$ cd my-project/

Joe@jpc MINGW64 /c/git-local-repository-example/my-project
$ git init
Initialized empty Git repository in C:/git-local-repository-example/my-project/.git/

Joe@jpc MINGW64 /c/git-local-repository-example/my-project (master)
$ echo test content > readMe.txt

Joe@jpc MINGW64 /c/git-local-repository-example/my-project (master)
$ git add *
warning: LF will be replaced by CRLF in readMe.txt.
The file will have its original line endings in your working directory

Joe@jpc MINGW64 /c/git-local-repository-example/my-project (master)
$ git commit -m "adding my-project"
[master (root-commit) 6decbea] adding
 1 file changed, 1 insertion(+)
 create mode 100644 readMe.txt

So far there's nothing new, we have been doing same thing in previous tutorials. Now let's host above project from a central location on the file-system which will be acting as remote repository.

Creating Remote Repository

Let's create a directory (my-project.git) representing the remote repository for our above project:

Joe@jpc MINGW64 /c/git-local-repository-example
$ mkdir my-project.git

Joe@jpc MINGW64 /c/git-local-repository-example
$ cd my-project.git

Joe@jpc MINGW64 /c/git-local-repository-example/my-project.git
$ git init --bare
Initialized empty Git repository in C:/git-local-repository-example/my-project.git/

Joe@jpc MINGW64 /c/git-local-repository-example/my-project.git (BARE:master)
$ ls -la
total 15
drwxr-xr-x 1 Joe 197610  0 Feb  2 13:41 ./
drwxr-xr-x 1 Joe 197610  0 Feb  2 13:40 ../
-rw-r--r-- 1 Joe 197610 86 Feb  2 13:41 config
-rw-r--r-- 1 Joe 197610 73 Feb  2 13:41 description
-rw-r--r-- 1 Joe 197610 23 Feb  2 13:41 HEAD
drwxr-xr-x 1 Joe 197610  0 Feb  2 13:41 hooks/
drwxr-xr-x 1 Joe 197610  0 Feb  2 13:41 info/
drwxr-xr-x 1 Joe 197610  0 Feb  2 13:41 objects/
drwxr-xr-x 1 Joe 197610  0 Feb  2 13:41 refs/

In above example we used git init --bare to create a bare repository.

What is a bare repository?

A bare repository doesn't contain a working directory. It does not have .git directory. It has similar directory structure what we see inside the .git directory. It has all commit history but without a parent .git directory and without a working tree.
By convention, bare repository main directory name ends with the suffix .git

Viewing bare repository logs

We can use git log for the bare repository to see the commit history. In above example, since my-project.git does not yet have any projects, it will return an error:

Joe@jpc MINGW64 /c/git-local-repository-example/my-project.git (BARE:master)
$ git log
fatal: your current branch 'master' does not have any commits yet

We can also use git branch command (but right now we have no project branches)

Joe@jpc MINGW64 /c/git-local-repository-example/my-project.git (BARE:master)
$ git branch -a

Pushing a project to the repository

So far there's no relation between our project (my-project) and the repository (my-project.git), but now we are going to push our project to the repository for the first time.

The push command syntax

git push <remote-url> <branch-to-push>

Let's use push command in our example:

Joe@jpc MINGW64 /c/git-local-repository-example
$ ls
my-project/  my-project.git/

Joe@jpc MINGW64 /c/git-local-repository-example
$ cd my-project

Joe@jpc MINGW64 /c/git-local-repository-example/my-project (master)
$ git push file:///c/git-local-repository-example/my-project.git/ master
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Writing objects: 100% (3/3), 215 bytes | 107.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To file:///c/git-local-repository-example/my-project.git/
 * [new branch]      master -> master

Note that we used file:// at the beginning of our repository url, indicating the repository is located on the local file system.

Let's see the logs again inside our repository:

Joe@jpc MINGW64 /c/git-local-repository-example/my-project.git (BARE:master)
$ git log
commit 6decbea4a2b4e9fe4f54814e9821d95ba74171b7 (HEAD -> master)
Author: Joe <joe@example.com>
Date:   Sat Feb 2 13:14:28 2019 -0600

    adding my-project

Joe@jpc MINGW64 /c/git-local-repository-example/my-project.git (BARE:master)
$ git branch
* master

Cloning remote project from a new client

Cloning a remote repository copies the target repository to local file system.

The clone command syntax

git clone <repository-url> [<target-directory>]

Let's create a new directory representing another client (other than the original one my-project) and clone the remote project

Joe@jpc MINGW64 /c/git-local-repository-example
$ mkdir other-client

Joe@jpc MINGW64 /c/git-local-repository-example
$ mkdir other-client/my-project

Joe@jpc MINGW64 /c/git-local-repository-example
$ cd other-client/my-project/

Joe@jpc MINGW64 /c/git-local-repository-example/other-client/my-project
$ git clone file:///c/git-local-repository-example/my-project.git/ .
Cloning into '.'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (3/3), done.

Joe@jpc MINGW64 /c/git-local-repository-example/other-client/my-project (master)
$ ls -la
total 5
drwxr-xr-x 1 Joe 197610  0 Feb  2 14:42 ./
drwxr-xr-x 1 Joe 197610  0 Feb  2 14:18 ../
drwxr-xr-x 1 Joe 197610  0 Feb  2 14:42 .git/
-rw-r--r-- 1 Joe 197610 14 Feb  2 14:42 readMe.txt

Joe@jpc MINGW64 /c/git-local-repository-example/other-client/my-project (master)
$ git log
commit 6decbea4a2b4e9fe4f54814e9821d95ba74171b7 (HEAD -> master, origin/master, origin/HEAD)
Author: Joe <joe@example.com>
Date:   Sat Feb 2 13:14:28 2019 -0600

    adding my-project

Tracking of repository

The time when we invoke the 'clone' command with the specified remote url, git automatically saves that as a tracked repository by the name of 'origin'. We can see that info by using git remote -v (-v flag is for verbose).

In above example after cloning:

Joe@jpc MINGW64 /c/git-local-repository-example/other-client/my-project (master)
$ git remote -v
origin  file:///c/git-local-repository-example/my-project.git/ (fetch)
origin  file:///c/git-local-repository-example/my-project.git/ (push)

That means next time we don't have to specify the whole url, just use the reference name 'origin' instead.

We can also add a remote explicitly by using following command:

git remote add my-origin-name <the-url>

Or we can edit the repository info by using following command:

git remote set-url my-origin-name <the-url>

Pushing new changes

Let's add a new file to our new client project and push that to the central repository:

Joe@jpc MINGW64 /c/git-local-repository-example/other-client/my-project (master)
$ echo new content > newFile.txt

Joe@jpc MINGW64 /c/git-local-repository-example/other-client/my-project (master)
$ ls -la
total 6
drwxr-xr-x 1 Joe 197610  0 Feb  2 15:23 ./
drwxr-xr-x 1 Joe 197610  0 Feb  2 14:18 ../
drwxr-xr-x 1 Joe 197610  0 Feb  2 14:42 .git/
-rw-r--r-- 1 Joe 197610 12 Feb  2 15:23 newFile.txt
-rw-r--r-- 1 Joe 197610 14 Feb  2 14:42 readMe.txt

Joe@jpc MINGW64 /c/git-local-repository-example/other-client/my-project (master)
$ git add *
warning: LF will be replaced by CRLF in newFile.txt.
The file will have its original line endings in your working directory

Joe@jpc MINGW64 /c/git-local-repository-example/other-client/my-project (master)
$ git commit -m "adding new file"
[master de56e3f] adding new file
 1 file changed, 1 insertion(+)
 create mode 100644 newFile.txt

Joe@jpc MINGW64 /c/git-local-repository-example/other-client/my-project (master)
$ git push origin master
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 8 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 281 bytes | 281.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To file:///c/git-local-repository-example/my-project.git/
   6decbea..de56e3f  master -> master

This time we used the repository reference name 'origin' instead of the whole url.

Let's see the logs in our central repository:

Joe@jpc MINGW64 /c/git-local-repository-example/my-project.git (BARE:master)
$ git log
commit de56e3f07beaadb5a95d0d1a32d6d17c322330e7 (HEAD -> master)
Author: Joe <joe@example.com>
Date:   Sat Feb 2 15:24:09 2019 -0600

    adding new file

commit 6decbea4a2b4e9fe4f54814e9821d95ba74171b7
Author: Joe <joe@example.com>
Date:   Sat Feb 2 13:14:28 2019 -0600

    adding my-project

Pulling the new changes

The git pull command is used to download the content from a remote repository and merge the changes to the local repository.

The pull command syntax

git pull <remote-url>

Let's go to our original client project /c/git-local-repository-example/my-project and pull the new changes from /c/git-local-repository-example/my-project.git.

Joe@jpc MINGW64 /c/git-local-repository-example/my-project (master)
$ ls
readMe.txt

Joe@jpc MINGW64 /c/git-local-repository-example/my-project (master)
$ git pull file:///c/git-local-repository-example/my-project.git/
remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From file:///c/git-local-repository-example/my-project
 * branch            HEAD       -> FETCH_HEAD
Updating 6decbea..de56e3f
Fast-forward
 newFile.txt | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 newFile.txt

Joe@jpc MINGW64 /c/git-local-repository-example/my-project (master)
$ ls
newFile.txt  readMe.txt

We have successfully pulled the changes from the repository.

See Also