Git collaboration: quick start

If you want to keep the git repository of your project clean and predictive (which is highly recommendable), here is a simple workflow to follow.
For the sake of this article, we are going to join the MongoDB project.

First step: work safely on your branch

When joining the project, the first step to get a local copy in your laptop:


$ cd my_working_directory
$ git clone [email protected]:nico/mongo.git

Once you do that, you have a copy of the source code locally. This is called the master:


$ cd ./mongo
$ ll
total 340
drwxrwxr-x 13 nico nico 4096 Jun 25 08:59 ./
drwxrwxr-x 3 nico nico 4096 Jun 25 08:56 ../
-rw-rw-r-- 1 nico nico 6709 Jun 25 08:59 .clang-format
-rw-rw-r-- 1 nico nico 29 Jun 25 08:59 .eslintignore
-rw-rw-r-- 1 nico nico 795 Jun 25 08:59 .eslintrc.yml
-rw-rw-r-- 1 nico nico 308 Jun 25 08:59 .gdbinit
drwxrwxr-x 8 nico nico 4096 Jun 25 08:59 .git/
-rw-rw-r-- 1 nico nico 74 Jun 25 08:59 .gitattributes
-rw-rw-r-- 1 nico nico 2145 Jun 25 08:59 .gitignore
-rw-rw-r-- 1 nico nico 337 Jun 25 08:59 .lldbinit
-rw-rw-r-- 1 nico nico 588 Jun 25 08:59 .pydocstyle
-rw-rw-r-- 1 nico nico 1703 Jun 25 08:59 .pylintrc
-rw-rw-r-- 1 nico nico 193 Jun 25 08:59 .style.yapf
-rw-rw-r-- 1 nico nico 366 Jun 25 08:59 CONTRIBUTING.rst
-rw-rw-r-- 1 nico nico 13460 Jun 25 08:59 CreativeCommons.txt
-rw-rw-r-- 1 nico nico 30608 Jun 25 08:59 LICENSE-Community.txt
-rw-rw-r-- 1 nico nico 1987 Jun 25 08:59 README
-rw-rw-r-- 1 nico nico 9933 Jun 25 08:59 README.third_party.md
-rw-rw-r-- 1 nico nico 173224 Jun 25 08:59 SConstruct
drwxrwxr-x 17 nico nico 4096 Jun 25 08:59 buildscripts/
drwxrwxr-x 2 nico nico 4096 Jun 25 08:59 debian/
drwxrwxr-x 2 nico nico 4096 Jun 25 08:59 distsrc/
drwxrwxr-x 2 nico nico 4096 Jun 25 08:59 docs/
drwxrwxr-x 4 nico nico 4096 Jun 25 08:59 etc/
drwxrwxr-x 33 nico nico 4096 Jun 25 08:59 jstests/
-rw-rw-r-- 1 nico nico 570 Jun 25 08:59 mypy.ini
drwxrwxr-x 2 nico nico 4096 Jun 25 08:59 pytests/
drwxrwxr-x 2 nico nico 4096 Jun 25 08:59 rpm/
drwxrwxr-x 5 nico nico 4096 Jun 25 08:59 site_scons/
drwxrwxr-x 4 nico nico 4096 Jun 25 08:59 src/

Now, in a big project like this, you shouldn’t work directly to the master. It is often not permitted to push your change in the master.
What we should do instead is to work on a separate copy that is commonly called a branch.

There should be a convention for the branch naming depending on the project. But as a rule of thumb, the branch name should be short, and self-describing.
Preferably, it will refer to a task (Jira task, GitLab issue, GitHub issue, etc.).

For our example, I’m going to change the MongoDB project documentation, so I call my branch “remove_obsolete_doc_part”.


$ git branch remove_obsolete_doc_part

You can see my local branches with that command:


$ git branch
* master ------------------------> The star here tells you that you are currently in that branch
remove_obsolete_doc_part

And You can see all local branches (local in your laptop and remote from the project) with the next command.
You’ll see two master branch, one called “remotes/origin/master” and one “master”. “master” is your local copy of
the master, while “remotes/origin/master” is the remote copy. “Origin” refers to the repository you cloned the code from (“git clone “).


$ git branch -a
* master
remove_obsolete_doc_part
remotes/origin/HEAD -> origin/master
remotes/origin/count-trace-events
remotes/origin/f1b99df5
remotes/origin/master
remotes/origin/r3.4.14
...
remotes/origin/v3.4
remotes/origin/v3.6
remotes/origin/v3.6.9-dbaas-testing
remotes/origin/v4.0
remotes/origin/v4.2
remotes/origin/v4.2.1-dbaas-testing
remotes/origin/v4.4

As you can above, there are many remote branches from the repository origin. But only two locals on your laptop.

Then, we need to switch the local files to our branch “remove_obsolete_doc_part”:


$ git checkout remove_obsolete_doc_part
$ git branch
master
* remove_obsolete_doc_part

Now I made my changes on the code and I can see the state of my change:


$ git status
On branch remove_obsolete_doc_part
Changes not staged for commit:
(use "git add/rm ..." to update what will be committed)
(use "git restore ..." to discard changes in working directory)
modified: README
deleted: docs/vpat.md

I want to commit those changes:


$ git add -A # ----------------> I add all my changes (-A) to the Git staging area (which means that will be committed at next commit time).
$ git commit -m "Remove obsolete documentation" # ---------------> I commit with a clear and short message of what I did.
[remove_obsolete_doc_part 1445bc4c6a] Remove obsolete documentation
2 files changed, 141 deletions(-)
delete mode 100644 docs/vpat.md

We can see the current state of our local Git repo with that command:


$ git status
On branch remove_obsolete_doc_part
nothing to commit, working tree clean

And we can review the previous commits wiht that one:


$ git log
commit 1445bc4c6a80a6dad5b285da4d5a81e9fa3a98cc (HEAD -> remove_obsolete_doc_part)
Author: nico
Date: Thu Jun 25 09:11:51 2020 +0000
Remove obsolete documentation

Then we are ready to push our branch to the remote repository:


$ git push origin remove_obsolete_doc_part
Enumerating objects: 7, done.
Counting objects: 100% (7/7), done.
Delta compression using up to 2 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 356 bytes | 178.00 KiB/s, done.
Total 4 (delta 3), reused 0 (delta 0)
remote: Resolving deltas: 100% (3/3), completed with 3 local objects.
remote:
remote: Create a pull request for 'remove_obsolete_doc_part' on GitHub by visiting:
remote: https://github.com/nico/mongo/pull/new/remove_obsolete_doc_part
remote:
To github.com:nico/mongo.git
* [new branch] remove_obsolete_doc_part -> remove_obsolete_doc_part

Second step: publish your contribution

Once you like what you did, you can merge your code into the master branch.
This can be done in different ways, and depending on the Git service provider, the philosophy can change.
For this article, I’m going to merge with the Git command-line tool.

Prior to merging your changes from the branch “remove_obsolete_doc_part” to the master branch, you need to
synchronize (pull) the remove master branch with your local one:


$ git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.

$ git pull #-------------------------> merge the remote code into your local code.

$ git fetch -p #-------------------------> optional but handy: it fetches remote branch other than the master and remove the local one that has been removed remotely.

Then, you can merge your local branch “remove_obsolete_doc_part” into the local master branch:


$ git merge remove_obsolete_doc_part
Updating 8b0f5d5e1d..1445bc4c6a
Fast-forward
README | 5 -----
docs/vpat.md | 136 ---------------------------------------------------------------------------------------------------------------------------------------
2 files changed, 141 deletions(-)
delete mode 100644 docs/vpat.md

At this stage, you may have conflicts because some parts of the code have been changed in the remote master copy while you were working locally. That’s perfectly fine and Git will show you the conflicting file in the staging area: `git status`. Just review the files and decide which part of the code you want to keep and commit.

The last operation conists in pushing your local copy of the master branch into the remote master so that everyone can enjoy
your changes:


$ git push
Total 0 (delta 0), reused 0 (delta 0)
To github.com:nico/mongo.git
8b0f5d5e1d..1445bc4c6a master -> master

Conclusion

Those are the minimum good practices you should follow if you plan to work on a project involving a few persons.
That guarantee that you can backup regularly your code without impacting the main project.

For more significant projects, you’ll see other concepts like the “pull request” or “merge request”.
Usually, you won’t be able to merge your changes directly into the remote master. Instead, you’ll have to create a request to push your changes into the remote master, and someone else will decide to approve the merging of your code, reject it or comment it if it requires more changes before merging.

Notes

Keep as much as possible your working branch in sync with the remote master. Ideally, execute full sync of your local copy before working on it every day:


git checkout master # Go the master branch
git pull # Get remote master changes into the local master branch
git checkout remove_obsolete_doc_part # Go back to your working branch
git merge master # Synchronize your working branch