In October 2020 I participated in the EthOnline hackathon in which I worked on a decentralized Github version. During the hackathon I created a simple PoC, showing that a Git repository can be represented by a Smart Contract and that the files/objects can be stored on IPFS. I received messages from people showing interest in my project. Therefore, I decided to continue working on this project.
So, what’s the current stage? I was able to release the very first alpha version, yay. It took me some time to get here since the Smart Contracts had to be rewritten, deployed on Polygon, and the git3 client had to be fixed. But, with this article I want to give you a step-by-step guide on how to use the Git3 Client, create a repository, and how to push content.
Keep in mind that it is an alpha stage and contains bugs! The Smart Contracts are deployed on the Polygon Testnet, so test as much as you want.
I tested the code on macOS Big Sur Version 11.2.3 using Python3.8 within the terminal. If you test it on a different OS, let me know, since I have not had the chance to test it on a different OS.
Without further ado, let’s get to it
The Git3 client is written in Python3 and you can install it using pip. To install the git3 client, run the following command in your terminal:
pip install git3Client==0.1.2
You should be able to run git3 in your terminal and receive a small message that command is required.
Since the repository we are going to create is represented by a Smart Contract, we will have to sign transactions. For this, we require a private key, which we are going to create using the ssh-keygen tool. Run the following command to create a new key in your terminal:
ssh-keygen -t ecdsa -b 256 -m pem
You can use the standard file name propose by ssh-keygen or type in your own name. In any case, copy the path where the private key is stored.
You have to do nothing else unless you want to export the private key and import it in MetaMask. In that case, run the following command in your terminal:
openssl ec -outform der -in [path_to_private_key] | hd
The output should look like this:
00000000 30 77 02 01 01 04 20 XX XX XX XX XX XX XX XX XX
00000010 XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX
00000020 XX XX XX XX XX XX XX a0 0a 06 08 2a 86 48 ce 3d
The 0x20 at position 6 says, that the following data is 32 bytes long. That is our newly created private key, which is represented as XX. Just copy this key into MetaMask and you are good to go.
Better tooling is required ;)
In order to initialize a new repository, all you have to do is to run
git3 init [name]
For this step-by-step guide, I will choose git3AlphaRepo as my desired name. Hence, we get the following command:
git3 init git3AlphaRepo
When it is successful, you should see the following message:
Initialized empty Git3 repository in:
[path]
Now it is time to add our first file to the repository. Go into the newly created repository and create a file. I am going to create a README.md file and write a sentence in there, as shown in the following Figure. Save the file.
Now it is time to add the file to the index. Therefore, we run the
git3 add README.md
command. Once we have added the file, it is time to commit. Run the
git3 commit -m “First commit message”
command. You will receive an error message, that no config file has been found. So, let’s create the config file first, and then we are going to redo the commit command.
There are currently two possibilities to create a config file.
We are going to take the second approach. Create a new file named config in the .git directory of your repository and write the following inside:
[user]
email = <[email protected]>
name = <your name>
IdentityFile = <path to your private key. Take path from the Private Key section.>
The configuration file is rather self-explanatory. There is nothing else you have to do, and you are ready to commit. Run git3 commit -m “First commit message” again and this time it is going to work.
Since it is the first time, we are creating the git3AlphaRepo repository, it only exists locally. In order to save the state of our repository remotely, we have to create a Smart Contract, which is going to store our information. Hold on, in order to create a Smart Contract, we require some tokens…
Well, let’s just get some ;)
Since we are using the Polygon Testnet, we can just go to the faucet and fill up our wallet with some tokens. Within your repository, execute git3 get-address command. This is going to print out your wallet address so that you can request tokens.
Fill out the site as in the following Figure, using the address which has been printed in your terminal, click on Submit and Confirm. Shortly after that, you should get a message that a few tokens have been successfully transferred into your wallet.
Time to create the remote repository.
Now that we have some tokens, we are ready to create a Smart Contract that is going to store our state. To create a new Smart Contract, just run
git3 create
and wait for the Repository git3AlphaRepo has been created message.
Since our Smart Contract has been created, we are now able to push the state of our repository. Just execute
git3 push
and see how one file after the other is pushed to IPFS and how the master cid is sent to the Smart Contract to be stored.
Well done, we initialized a local repository and pushed it.
One question which arises is, how are we or anyone else able to clone our
repository? In order to clone you have to know the wallet address and the
repository name. Having these two pieces of information, we are able to clone our repository.
Here is how:
git3 clone [wallet address]/[repository name]
The wallet address and the repository name are joined by a slash. Don’t forget that. In case you are cloning the repository into a different location on your local machine, don’t forget to add the config file in the .git folder.
Great, we have been able to clone a repository, but it has been updated and our cloned repository is out of sync. In order to get the news changes from the remote repository, we have to pull. git3 pull is all you have to do. In order to demonstrate this, I updated the README.md file in the first repository by adding another sentence to it, as shown in the next Figure.
Then I am going to the cloned repository and run the git3 pull command. Et voila, the README.md file in the cloned repository has been updated with the added sentence.
What if you did some work in the first copy of the repository and pushed it, but also did some changes in the second copy?
Let’s assume I added another line to the README.md file in the first repository (as shown in the next Figure) and pushed it.
After that we are going to the second clone of the repository and add a different text at the end of the README.md file and try to push it.
If you try to push you should receive an error message:
Remote repository is ahead. Fetch and merge the changes first
Alright, let’s fetch first:
git3 fetch
After the fetch we are going to merge:
git3 merge
The merge command currently only merges fetched changes with the local files. You are currently not able to merge branches or anything else.
Great, as soon you merged have a look into the file if there is a merge conflict. In case there is, resolve it, add the file, commit it with a proper message, and push.
Your repository has now the newest state.
As you see it is possible to do some basic git commands with the git3 client. It still contains bugs that have to be resolved.
If you have any feedback, I would like to hear from you. Do feel free to share your thoughts on this with me or perhaps you found some other issues?
Do you like the git3 project? Check out the repository: https://github.com/varkiwi
Check out also the grant on Gitcoin: https://gitcoin.co/grants/1712/git3
Disclaimer: The author provides this code and software “AS IS”, without
warranty of any kind, express or implied, including but not limited to fitness for a particular purpose and non-infringement. In no event shall the
author be liable for any claim, damages or other liability in connection with the software or code provided here