Collaborative project work involves a variety of corporate tools and platforms. For knowledge accumulation and documentation - Wiki platform, for workflow management - CRM, for data management and access - databases, etc. However, an important component when working with code, documentation, and files is Git!
What is Git?
Git is a repository version control system, which is a platform for managing repositories stored on a server. It is mainly used to distribute software to an unspecified number of people or to provide access for a team to collaborate on a project. Let's start by defining the concepts and entities that are used when working with Git:
- Working tree - The folder where the files for user work and the .git directory are stored;
- Index - An intermediate module that stores Working tree changes;
- Commit - A snapshot of the working directory, taking into account the changes written to Index;
- Repository - an archive of commit or snapshots of the working directory.
The whole work with repositories can be visualised as a diagram of three entities:
The user experience starts by initialising the repository to a specific folder with the command:
git init /path
After that, three main entities are created for Git: Working Tree, Index, Repository. The folder in which the .git directory is created is considered the Working Tree and is where the files are stored. All changes made to the working directory are registered in Index with the command:
git add /path
The Working Tree changes have been registered, after which you can generate a Commit or snapshot of the working directory, which will be sent to the repository.
git commit ./
At this point the commit has been generated as an object, which is stored in objects. We can then direct it to the local repository, by default with the command:
git push origin master
Where origin is the path and master is the master branch. Or override the origin path to a remote repository and run the command:
git remote add origin git@ip-address:/path-to-repository && git push origin master
The Commit will then be sent to the repository or Repository, where it will register a commit named master. In the future, any user can download this version of the commit and use it locally. Implemented with the command:
git clone git@ip-address:/path-to-repository
How do we put this into practice? Let's build our own Git server!
How to quickly create your own Git server?
All actions can be performed on powerful cloud servers. Serverspace provides isolated VPS / VDS servers for common and virtualize usage.
It will take some time to deploy server capacity. After that you can connect in any of the convenient ways.
Let's install the git package on the machine via the command, for deb-like distributions:
apt install git
And a separate command for rpm-like versions, via the yam/dnf package manager:
yam install git
For authentication, the server will run SSH under the git user and authenticate via keys. To prevent the user from executing malicious commands in a normal shell, it will be necessary to specify a git-shell for the user, through which only git commands can be executed. To do this, let's create a git user:
adduser git -c "Login point" -s $(which git-shell)
Since the SSH server is already configured for key-only authentication, we need to pass the list of users' public keys to the git home directory.
mkdir /home/git/.ssh && ssh-keygen git
Under discretionary access rules, keys will inherit the creator user's permissions and need to be changed, as does the storage directory:
mv /home/root/.ssh/git /home/git/.ssh/git \
mv /home/root/.ssh/git.pub /home/git/.ssh/git.pub \.
cp /home/root/.ssh/authorised_keys /home/git/.ssh/authorized_keys
Now let's go to the client and find its public key, and if it doesn't have one, then augment it with the ssh-keygen command:
cat /home/your-user/.ssh/id_rsa.pub
Copy the displayed key, it should look like this:
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCjqQj9A+66iGuq3DYVXWTyHNBklggCdesWQqyIjLfo+aHirIfv5in7d2jFsv6w3HqBumi7PTyIVRsH50y5AWO4nxhE9RJykdKnZ9NAok6XoJk//nVmafIDpyFf5MxrqId02tyrdPT8kIJHPDM2uEANoIpRSvEYqaC39dN1MHK8208nPVxdJ2FV/PNBmBgDnG+Bl89THg6vHUaEfVfNVw5qz1rm7OZ8Z9Eksqv0ErSUq0vHDnJh24oTf9wh6iWDOEgFhVOWQjlLzN2cZn1yk4Ol2hxmZwUcrpjyLRg7n7/Djc1RKJPfxRqOftb8GY8ZICpWJSKOUPooVE9dMxFrgRcb0MQVtreGY2ZU8awcLhpKkvOz4MnwzdbmlUIGprCxdmfy0bQT6QpbKPWEBgee+6uGmVsnP6iJQnFRwNSQw3bxgnQue8l0r2IJ9LTzXVNkjaIJTu17QOsH+HSXcFlFok44PUEqSlaDL+QWyf4DZ8QIknzJ7eorgNxGjCmmqhtLrDc= root@df
To protect the device from accessing other servers - let's add no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty to the beginning of the line and get the following entry and immediately write in the authorised keys. Don't forget to switch back to the server, because that's where we insert the client key:
echo "no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCjqQj9A+66iGuq3DYVXWTyHNBklggCdesWQqyIjLfo+aHirIfv5in7d2jFsv6w3HqBumi7PTyIVRsH50y5AWO4nxhE9RJykdKnZ9NAok6XoJk//nVmafIDpyFf5MxrqId02tyrdPT8kIJHPDM2uEANoIpRSvEYqaC39dN1MHK8208nPVxdJ2FV/PNBmBgDnG+Bl89THg6vHUaEfVfNVw5qz1rm7OZ8Z9Eksqv0ErSUq0vHDnJh24oTf9wh6iWDOEgFhVOWQjlLzN2cZn1yk4Ol2hxmZwUcrpjyLRg7n7/Djc1RKJPfxRqOftb8GY8ZICpWJSKOUPooVE9dMxFrgRcb0MQVtreGY2ZU8awcLhpKkvOz4MnwzdbmlUIGprCxdmfy0bQT6QpbKPWEBgee+6uGmVsnP6iJQnFRwNSQw3bxgnQue8l0r2IJ9LTzXVNkjaIJTu17QOsH+HSXcFlFok44PUEqSlaDL+QWyf4DZ8QIknzJ7eorgNxGjCmmqhtLrDc= root@df" >> /home/git/.ssh/authorized_keys
And the final touch, permissions, let's deny access to keys and grant permissions to git files:
chmod 700/home/git/.ssh/authorized_keys \
chown -hR git:git /home/git/
Let's create the repository with one team! Or almost one:
mkdir -p /srv/git/proj.git \
git init --bare /srv/git/proj.git
Great! Now the repository is created and you can start working with it, taking into account the condition that it is of bare type. You can read about the difference between bare and non-bare in our article. In this case, the repository type allows you to access it only via pull/push/fetch. Let's create a repository on the client with the command:
git init /path-to-folder-with-files \
git add . \
git commit \
git remote add origin git@ip-адрес-сервера:/srv/git/proj.git
After that the repository will be locally created on the client, the files will be registered and the commit with the server endpoint will be prescribed. And it remains to upload the new data to the server repository:
git push origin main
Voila! The server is up and running, and then other users can upload the existing repository with the command:
git clone git@ip-адрес-сервера:/srv/git/proj.git
However, don't forget to pre-populate their public keys in the trusted file as above!