Git 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.
‘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 firstname.lastname@example.org
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
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.
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 email@example.com:/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 firstname.lastname@example.org:/opt/git/cross_platform_app.git (fetch) origin email@example.com:/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.