How to work with git - a newbie guide
Posted in git on March 4, 2019 by Adrian Wyssmann ‐ 12 min read
I got in touch with git when I was starting using Github. However as these projects were merely single contributor projects, some basic commands did it for my work there. There was no branching, no rebasing or whatsoever. Now after working on a daily basis with git and using it in big(ish) teams, I thought to write down a little guide for newbies on how to work with git.
Obviously best way to get on with git is to read the official documentation at https://git-scm.com/book/en/v2/ which is quite comprehensive. I try to sueez the information a bit into a single page focus on the most important stuff
What is git
Well most of us developers know what’s git. However some come from a different vcs like svn, so therefore let’s see what Wikipedia says:
Git is a version control system for tracking changes in computer files and coordinating work on those files among multiple people. It is primarily used for source code management in software development,[8] but it can be used to keep track of changes in any set of files. As a distributed revision control system it is aimed at speed,[9] data integrity,[10] and support for distributed, non-linear workflows.[11]
As with most other distributed version control systems, and unlike most client–server systems, every Git directory on every computer is a full-fledged repository with complete history and full version tracking abilities, independent of network access or a central server.[13]
Important is to understand that the last part: it is a distributed version control systems which means you can work (e.g. branch) locally without having a connection to the internet. I see the following benefits over other version control systems:
- it is decentralized so every developer has a local copy of the full version history of the project on their individual machine
- feature branches allow to do experimental development and rapid prototyping without breaking existing code
- you can rewrite the history, this helps to have a clean commit history
Here some additional resources to read
- Git/Bitbucket Benefits
- What are the advantages of Git over SVN
- Why you should switch from subversion to git
- Why is git better than subversion
Just for completeness, there are also critics or adovation for other source controls and here are some interesting points about
- Subversion vs. Git: Myths and Facts
- A year of using Git: the good, the bad, and the ugly
- 10 things I hate about Git
So, git is not necessarily superior to other version controls but it does some things nice and is - so would I say - a defacto standard by now. So it is essential a developer knows about it.
Install and configure git
Installation on Linux is usually easy as most distrbibutions come with a git-package. On Windows you can download the executable from the official page or you use a package manager like chocolatey.
Before committing or pushing, ensure you have set your user name and email correctly configured. This information is used for the commits, and is imprtant to be correct as the e-mail address is what “identifies” you as a commiter
Workflow
There are different ways to work with git, but mainly there are 2 common workflows which are mostly used: Gitflow and GitHub Flow. Which flow fits better for you, depends on the needs of the projects and shall be carefully discussed with the respective developers.
Usually you use a platform like Github, Gitlab or Bitbucket to host your code. This helps you to easily share code among other developers and brings other benefits like Pull/Merge Requests. Later more to that.
Where to start
Well you can start by creating your first project from scratch. Usually git init
suffices. Now you can start creating code and adding them to your git repo.
If you want to share the project with others you usually would upload it to a remote repo. Thus you need to let your git repo know where that is. Each remote has a name - usually origin
. You may have more than one remote, but lets start with one. Ensure youe have an empty remote repository created (e.g. on Github), so the changes can be pushed to it. Then configure the remote and push it upstream.
The example above shows a connection to github using https, but you could also use ssh
Create Branches
A “branch” is an active line of development. The most recent commit on a branch is referred to as the tip of that branch. The tip of the branch is referenced by a branch head, which moves forward as additional development is done on the branch. A single git repository can track an arbitrary number of branches, but your working tree is associated with just one of them (the “current” or “checked out” branch), and HEAD points to that branch.
Whereas in svn you have a trunk
in git you have a master
branch is a permanent branch which contains latest code which is in a production-ready state. So you usually work in “feature” branches. A branch usually looks like prefix/unique-identifier
whereas the prefix is something like feature
, bugfix
or your username
. Later is usually the commn whay when working on Github. The unique-identifier can be whatever but tTry to find a unique name to avoid name collisions when working on your branch. The branch is individual to a Developer and often to small implementations. It not always reflects an issue or a story. Usually it makes sense to have some common rules. In the company I am working we usually use feature
, bugfix
, release
as prefix and the issue/story item as unique-identifier.
Also essential is that only one person is working on a branch to avoid collision or that you overrite changes of somebody else - yes multiple people could work on the same branch if you are very careful, but I personally don’t like it.
Below we clone an existing repo, make a branch, add and commit a new file. This happens locally so far nobody knows about your changes other than you.
Now you need to push your changes upstream as already shown above. You can also use the short-form -u?
Master Branch
As already mentioned, the master branch must always be potentially releasable. If you merge features into master, you acknowledge these changes will be contained in the next release. Usually would configure your remote in way that it is not possible to push changes of a master branch. Also would you ensure that only certain people can merge changes to the master or at least that they only can merge them once a peer review has happened.
When working on your branch commit regurarly. In case something goes wrong you can go back. Ensure to write useful git commit messages according to these 7 rules:
- Separate subject from body with a blank line
- Limit the subject line to 50 characters
- Capitalize the subject line
- Do not end the subject line with a period
- Use the imperative mood in the subject line
- Wrap the body at 72 characters
- Use the body to explain what and why vs. how
There may be some additional rules like to directly transit issues from one state to an other (e.g. close issues witha commit). But this depends on your remote.
You can also create branches from your branches or stash changes in a dirty working directory away and reuse them later.
Tags
Git also knows the concept of tags and as https://stackoverflow.com/questions/1457103/how-are-git-tags-different-from-git-branches point out
A tag represents a version of a particular branch at a moment in time. A branch represents a separate thread of development that may run concurrently with other development efforts on the same code base. Changes to a branch may eventually be merged back into another branch to unify them. From the theoretical point of view:
tags are symbolic names for a given revision. They always point to the same object (usually: to the same revision); they do not change. branches are symbolic names for line of development. New commits are created on top of branch. The branch pointer naturally advances, pointing to newer and newer commits.
Closing Work
Before you create a Pull Request (PR) apply the changes from master branch in order to ensure a smooth merge of your PR (i.e. no merge conflicts)
Rewrite your history
Before creating a pull request ensure that your history is clean so it makes it easier for the reviewers - see also Rewriting History
One of the cardinal rules of Git is that, since so much work is local within your clone, you have a great deal of freedom to rewrite your history locally. However, once you push your work, it is a different story entirely, and you should consider pushed work as final unless you have good reason to change it. In short, you should avoid pushing your work until you’re happy with it and ready to share it with the rest of the world.
Git allows you to “rewrite” the commits already done by
- change the order of commits
- change the commit message
- *modify files in a commit
- squash multiple commits to a single one
- split a commit into multiple commits
- removing commits
You need to be careful cause a some of these operations changes the SHA-1 of the commit. This means when you already pushed your changes to your remote and the e.g. changing the last commit, it will appear that there is one change in the remote and one locally. So you should
force
push your changes. However, this lead to the same problem if somebody is working on the same branch.
Changing the last commit
This is like a small rebase. The following command replaces that last commit with your new, improved commit:
git commit --amend
Changing Multiple Commit Messages
The following command does modify not only the last but all commits as far back as you want (e.g. in the example below we will edit the last 3 commits). You can also specify a commit-hash
Also provide the -i
option to make the rebasing interactive so the tools stops after each commit you want to modify.
Running this command gives you a list of commits in your text editor that looks something like this:
Commits are listed in the opposite order than you normally see them using the log command i.e. oldest commit is shown on top. This also indicates the order in which the commits will be processed.
You need to edit the script so that it stops at the commit you want to edit. To do so, change the word pick
to the word edit
or reqord
for each of the commits you want the script to stop after. When you save and exit the editor, Git rewinds you back to the last commit in that list and drops you on the command line
Squash vs. Fixup
Squash squashes the changes of multiple commits into a single one. Fixup is basically the same as a squash. The main difference is that for a squash git gives you a dialog to modify the commit messages (per default containing the commit messages of each individual commit) whereas fixup ignores the commit messages of the commits.
Create PR
With a Pull Request (PR) or Merge Request - naming depends on the remote - a developer asks the changes to be merged to another branch. This is usually done via the GUI of the remote usually adding some additional feedback what is expected to be reviewed and other useful information to the reviewers
One or more peers opens the PR in the remote and reviews the code in accordance with Code Review (Pull Request). Usually it’s good to
- add comments directly on the affected line of code
- add more information or questions to the activity
After the review, the reviewer either approves or marks the PR as “needs more work”:
PR needs more work
In case the code needs rework, the author shall continue to work on the branch until the peers ack the PR. Here a useful command to Fixup your PR issues :
PR approved
Once the PR is approved there is nothing else to do for the reviewer. So the PR can be merged. It’s usually a good practice to delete the branch in the remote
Keep in mind that deleting the branch on the remote does not delete your local branch. You have to do this manually
In case you did not delete the remote branch during the merge of the PR, you can delete them afterwards via the GUI of the remote or you can run this command form your local workspace
References and recommended readings
E-Learning
Branching
- A successful git branching model
- Choose right git branching strategy
- git branching guidance
- A succesful git branching model considered harmful
- Git Branching Branches in a Nutshell
- Git Tools Rewriting History
- Maintain Clean git history
Maven and releaseing
- Atlassian: interesting point of view, to further elaborate
This is one of the real problems with maven. Checking the version into a file in Git is a bad idea (we have the same problem in Stash though)
- How to make a release with Git and Maven via JGitFlow
- [DZone: Whey I never use maven release (Read also comments, very interesting)](https://dzone.com/articles/why-i-never-use-maven-release]