Setting up Git Collaboration for your Internal Developer Team

git-logoGit is the defacto go to version control tool if you have reached a point where you need collaboration between your developer team members.Git being amazing at its job though ,many entry level people find it hard to set up and shy away from its benefits if there is no one around to guide them.In this tutorial we will see how to set up git for use in a small team of developers on a local network(which is the case for many small companies). Although we will talk about some basics of git ,we assume that you can do basic adding,committing and branching for your git repositories,if you can’t do that already ,please read about it and come back here.Now the fun begins.

Git can benefit you even if you are a solo developer

People often think of git only when they need team collaboration on a software project.But this shouldn’t be the case as it greatly helps in keeping track of the changes you have made over time and gives you an easy way to visit your history if you need so and even turn your working directory to a certain point back in history.To make this clear,head to one of your git repositories and run this log command.

$ git log --oneline
f6e37a7 Added the first function
ac2b2dc Merge remote-tracking branch 'origin/master'
2c957c3 Added only the main file from the remote repo
078ab1d added main function
7ba28b5 Added second include file
b3d0182 Added the include directives
f8d3284 User git added to README
20d3cb1 Updates readme with license info
46e1b2f Initial commit

You can see my changes referenced by numbers like ‘f6e37a7’. If you don’t know what those are just think of them as particular points in the timeline of your project as shown in the figure below.

log_timeline

‘f6e37a7’ is the head or tip of your project timeline .It is also where the head of my branch(master) is pointing currently.If I wanted to turn my project to the state it was in when I “Added second include file ” which corresponds to the SHA of ‘7ba28b5’ I would do that by simply typing the following git command.

gakwaya@bakoko MINGW64 /d/igipimo/gittest (master)
$ git checkout 7ba28b5
Note: checking out '7ba28b5'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

git checkout -b <new-branch-name>

HEAD is now at 7ba28b5... Added second include file

gakwaya@bakoko MINGW64 /d/igipimo/gittest ((7ba28b5...))

If you added the second include file two years ago ,your working directory project is turned back to the state it was exactly in two years ago.When you are done looking around and doing whatever got you to look at your history ,you can come back to the current state with the following commands.

gakwaya@bakoko MINGW64 /d/igipimo/gittest ((7ba28b5...))
$ git checkout f6e37a7
Previous HEAD position was 7ba28b5... Added second include file
HEAD is now at f6e37a7... Added the first function

gakwaya@bakoko MINGW64 /d/igipimo/gittest ((f6e37a7...))
$ git checkout master
Switched to branch 'master'

gakwaya@bakoko MINGW64 /d/igipimo/gittest (master)
$ git log --oneline
f6e37a7 Added the first function
ac2b2dc Merge remote-tracking branch 'origin/master'
2c957c3 Added only the main file from the remote repo
078ab1d added main function
7ba28b5 Added second include file
b3d0182 Added the include directives
f8d3284 User git added to README
20d3cb1 Updates readme with license info
46e1b2f Initial commit

One takes us to the latest point in time ‘f6e37a7’ and the other which is the same as (master) as it is where the master branch is pointing.You might be thinking , this is great,now I can test new ideas ,commit them and if something goes wrong along the way I can checkout the latest working bug-free state of the project.This could work but it can cause serious problems when collaborating with others and it is not the recommended way to try out new ideas.You try out ideas in branches which I am not going to explain here.The official doc does a way better job at that.Now that you know how git can help you out as a solo developer ,how do I setup a git server for my team?

Setting up Git for collaboration.

To make the explanations easier ,we are going to imagine a real life scenario where a team of three people is working on a piece of cross platform software that runs on Linux ,Mac and Windows.The central point of the project will live on the Linux machine it is where developers will be pushing and pulling changes to/from.The first obvious requirement is that these three computers need to have network connectivity between them.Another special case of our scenario here is that the Linux developer will be working on the same computer that hosts our central point for collaboration.Make sure each computer has git installed and that the basic configuration for git is done.Again the official doc gives more details on these configurations.

git config --global user.name "John Doe"
git config --global user.email johndoe@example.com

 

Now we create the git user that will be used to commit changes.Please note that the git user is may be different from the system os user which we are setting up as git now.

sudo adduser git
su git
cd

The adduser command will prompt you for password and other info.Just put in your info and continue.Change to the git user you just created and cd into git’s home directory.Now we need a way for our Linux server to authenticate the users that want to push/pull commits to our git repo.We use ssl certificates for this purpose.The way this works ,is every user is going to generate a key pair ( which is a public and a private key).He is going to keep the private key in the .ssh/ directory residing in his home directory and send the public key to the server.The server is going to use this public key to know if the user who wants to push/pull changes should be trusted.If this doesn’t make any sense ,just look at the commands below,it may just kick in.Check the home directories of the user’s for the .ssh/dir.Users on Windows usually have a hard time figuring out where the .ssh/ directory is.Mine was stored in

C:\Users\gakwaya\.ssh

as shown below.Another friendly note to Windows users is that we are using git bash that you get after installing git from the official git page.Not the one that comes with github or the one from elsewhere.

githome

If you don’t find the two files : id_rsa and id_rsa.pub in the .ssh directory then you need to generate the key pair.With the command below.

ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/git/.ssh/id_rsa):
Created directory '/home/git/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/git/.ssh/id_rsa.
Your public key has been saved in /home/git/.ssh/id_rsa.pub.

Now that users have keypairs send the keys ending in .pub to the Linux computer.In our case it may be id_rsa_win_pc.pub ,id_rsa_mac.pub.The Linux developer doesn’t need ssh authentication as he will be working directly on the Linux pc.Now we assume that the files are stored on the Linux computer in location /home/git/users_keypairs/.

Now we head back to the Linux machine and cd into the home directory and create git user’s .ssh directory if it is not there already.In that directory ,we create a file named authorized_keys and set give access read write access only to the git user.

mkdir .ssh && chmod 700 .ssh
touch .ssh/authorized_keys
chmod 600 .ssh/authorized_keys

Now what is this file and what does it do?Ssh uses this file to authenticate your users.How does that work?You append the public keys you got from your users to the authorized_keys file and whenever a user tries to connect to the Linux computer with ssh ,ssh checks to see if his public key has been appended to the authorized_keys file if yes the user is given access ,if not he is cut off.If this sounds complicated ,just follow the steps below to append the users’ public keys to the authorized_keys file.Remember we assume you copied them in the /home/git/users_keypairs/ directory?

cat  /home/git/users_keypairs/id_rsa_win_pc.pub >> /home/git/users_keypairs/.ssh/authorized_keys
cat  /home/git/users_keypairs/id_rsa_mac.pub >>  /home/git/users_keypairs/.ssh/authorized_keys

With this in place ,the remaining thing on the server is to create the git repo .Head to the computer that is going to host the central repository and create a folder that holds your git projects.Mine is in /opt/git.

cd /opt/git
mkdir cross_platform_app.git
cd cross_platform_app.git
sudo git init --bare
Initialized empty Git repository in /opt/git/cross_platform_app.git/

You may have noticed the –bare flag.A bare repo is a repo with no working directory attached to it.In other words you can’t run commands such as git status on it.It is meant to be the central communication point for collaborating developers.The last thing to do on the server side is to tighten security by only allowing the git user to access the /opt/git directory.

cd /opt/
sudo chown -R git:git git

The server side setup is done for the moment.We can go to the Windows and Mac computers and set up repositories that will push/puss to/from our cross_platform_app.git bare repo.Head to the Windows computer and create a directory to contain your repo,we call it myproject here.

cd myproject
git init
git add .
git commit -m 'initial commit'

We initialize a git repo ,this time not as a bare repo because we need it to have a working directory.We do the usual add and commit stuff.Now we need to connect this repo to our bare repo that lives on the linux computer.This is called remoting in Git.You add a remote link using the git remote add command as shown below

git remote add origin git@192.168.1.111:/opt/git/cross_platform_app.git

The IP address can be replaced with a hostname or whatever your dns node is configured to resolve as. ‘origin’ is just the name of our remote link ,you could have put anything in its place but it is good practice to name it origin within the gig community.Now The windows user and push his changes as follows

git push origin master

How do others clone the repo?

At this point the Windows user ,who added the remote link and pushed his first change can fully push and pull changes.How about the other developers for example the mac guy.Not to worry ,he can just clone the repo using the ssh protocol ,you may remember that we configured the server to trust his public key.He clones the repo as follows:

git clone git@gitserver:/opt/git/cross_platform_app.git
cd project

Applies changes as he sees fit ,commit and push them back to the bare repo just like we did before

git push origin master

What about the user on the machine holding the remote repo?

There really isn’t that much change in the way the user on the Linux machine holding the central repo communicates with it(the central repo). Simply cloning the full path to the repository does the job.

git clone /opt/git/cross_platform_app.git

No ‘git remote add’ for cloned repositories?

You may have noticed that we haven’t run the git remote add command to add remote links to our cloned repositories.This is because the clone command does that for you automatically.You can confirm your remote links by the following command.

git remote -v
origin  git@192.168.1.111:/opt/git/cross_platform_app.git (fetch)
origin  git@192.168.1.111:/opt/git/cross_platform_app.git (push)

git remote is a powerful command in managing your remotes .You can add and remove them and much more.You can learn more bout it from the official docs.

Now we can effectively push changes to the remote repo but we also want to be able to pull changes from others ,see them and merge the in our own local working directory.

Pulling changes form others.

From your local repositorie’s perspective , a remote repository is just like a branch.This allows you the local repo user to interact it the way you are used to interact with branches.You can confirm this with the command

$ git branch -r
  origin/master

The -r flag only shows remote links.Now that we know about the remote branch ,we can pull remote changes in our local origin/master branch with the git fetch command.

git fetch origin master
From 192.168.1.111:/opt/git/cross_platform_app
 * branch            master     -> FETCH_HEAD

Now the origin/master branch has the latest changes.We can compare it to our master branch it two ways.One way is to see the changes origin/master has that we(master) don’t have.We dot that like this

git log --oneline master..origin/master

This the usual log command,but it filters changes that the upstream repo has that we don’t have.If there are commits we don’t have they would show up here.Just like the normal log command does.Another way is to show the changes that we have that origin/master doesn’t have.We do that as follows.

git log --oneline origin/master..master

This is just my way of doing these things.Some shells are configured to automatically show you whether you are ahead or lagging behind the upstream repo.We won’t be configuring that here.

Merge those changes in

If you find that there are changes present in the upstream repo that you don’t have ,you merge them just like you are used to .

git merge origin/master

This puts you up to date with the upstream bare repo.Merging changes can be hairy in not just Git by any Version Control System out there.You need to be careful in merging changes.A good rule of thumb is to merge as often as possible and handle small problems as they arise.

We have seen a lot of information in this tutorial and some of the things may have not stuck in so far.Don’t just read this ,do actually try it using two or more computers and run the actual commands.It helps ,also do look up other tutorials.The official doc itself is enough for some people.I hope this has been informative to you and I would like to thank you for reading.

Posted in linux tricks, Servers, Tips and tricks, Tutorials and tagged , , , .

Daniel Gakwaya loves computer Hardware/Software.He is a Software Engineer at BLIKOON and lead developer of bliboard-The whiteboard system currently marketed by the company.He is known to hack around on any piece of tech that happens to pick his interest. More on his tech endeavors here
Follow him on Twitter

3 Comments

  1. Setting up a Git central repository that is accessible by remote protocol is tricky. The easiest way to do it is to use an existing system such as Gitosis or GitHub .

    • I agree that Github or Gitosis are great if “they fully meet your requirements”.Github is not free if you re not open source and Gitosis is not that easy to set up for many people.The procedure in this tutorial is recommended for small teams that favor ease of setup and keeping things internal on the local network.

  2. You have forked a project from github or whatever, have done your changes and pushed to your fork. The original project has made changes that you are interested in. This is how you sync those changes in.

    git remote add upstream ORIGINAL_REPOSITORY_URL

    This will set your upstream to the repository you forked from. Then do this:

    git fetch upstream

    This will fetch all the branches including master from the original repository.

    Merge this data in your local master branch:

    git merge upstream/master

    Push the changes to your forked repository i.e. to origin:

    git push origin/master

    Voila! You are done with the syncing the original repository.

    Credit :

Leave a Reply

Your email address will not be published. Required fields are marked *

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.