Git life
I have been using Git for more than 2 years now and I thought it was time I reflected on my story with it and jot down the things that have become second nature.
What is git?
I am going to keep it simple and give a practical summary of what it is.
It is a command-line software that will help remember and track for you different versions of your workspace (a folder, a file etc). It is very good at doing its job, allowing you to name things and assign messages to changes.
For an official definition, head over to GIT SCM
Why git?
As developers, we write a lot and we remember too little of that. Git was built long ago as there arose the need to make machines remember for you what changes you made at different stages, compare them, get back to when things go wrong and allow multiple people to contribute to the same workspace.
Today, that’s why we still use and need Git or its alternatives. Here’s a quick checklist of things it helps with day to day:
- Gives developers confidence and independence when working on a shared project
- Keeps trail that can be reverted to when things go wrong, and to study when and why a certain decision was committed in history
- Gives developers the ability to shorten and divide their tasks as well as reviewing for code quality async
- Makes development and deployment lifecycle faster
… and many, many more
My initial impression
One thing with me when encountering new things is trying to be open-minded and finding what is intriguing or genius about something. When I came across TFS and Git, my initial reactions was “wow, what a heritage”. Why was I surprised? Because developers solved a painful problem of theirs via software. The art of automating as many things as a possible so you can build the next automation for the automatable processes in the real world.
As for using git, I knew I needed to get comfortable what the words used in commands actually mean in plain English and how that relates to their role. I found easy the basics e.g. create a commit, create a branch, push etc.
The commonly used commands
Here are the commands I use on a daily basis. Note: this list contains commands that are mutually exclusive
-
git remote updateI use this to check if there has been any updates in the remote repository my local one is connected to
-
git checkout BRANCH_NAMEFor navigating to a branch I want to work with
-
git branch -m NEW_BRANCH_NAMEWhen I need to create a new branch. I will then move to this branch using the git command above it
-
git pullTo sync current local branch with any new changes found on the remote branch. This is branch specific, it will pull from the remote branch that your current branch is connected to
-
git merge SOURCE_BRANCH_NAMEWhen I need to merge changes from a different branch to the current one I am on
-
git rebase SOURCE_BRANCH_NAMEFor merging changes from a different branch to mine, except it preserves the order that things came in from the source branch.
It collects the stack of history that is different from what is in the source branch and moves it aside. Then, brings the stack of new history that my branch doesn’t have from the source branch and stacks it on top. Then brings what we put aside and puts it at the top of the stack.
If the history between the two histories got out of sync in a disorderly way, then conflicts will arise. You will learn how to deal with some of the cases in the next section
-
git commit -m "YOUR_MESSAGE_ABOUT_WHAT_YOU_DID"This is how you’d create a point in the timeline that
gitkeeps. And you have to assign a message, even as short as just 1 character (but how useful would that be?).For me, I usually write something like this:
[+] Adds component for ... [+] Adds functionality for ... [*] Amends component/functionality [*] Fixes issue with .... [-] Removes unnecessary ... [-] Removes functionality or fault etc ...It summarises my todo list before I started working, and what kind of impact that has on the codebase.
-
git push --set-upstream origin BRANCH_NAMEFor creating a mirror “remote” branch in the remote repository I am connected with, here referred to as “origin”. This will copy over everything in the local branch and create a link between for future exchanges e.g. pull, push etc
After this, you can then normally just do
git pushfor the rest of the branch’s life except in certain scenarios (will cover one or two such scenarios in the next section).
The get-out-of-jail git commands
-
git rebaseWe use this as the default way to merge things.
Conflicts do happen, don’t worry … git will tell you when there are
How do you resolve them? It depends. I will give my two cents based on the two systems I use.
I primarily use VS code so here we go.
- Open the files identified as having conflicts in VS code. Find areas flagged and accept which of the changes you want to keep for each file. You can also see files with conflicts in the changes tab inside VS code under “Merge” I believe (See VS Code src control)
- Then stage these changes via
git add *or replace*with any specific folder or file path, Then continue to the next or final stage of the rebase process viagit rebase --continue
If you use Visual Studio, there’s an option to open in its default 3 way merge tool and choose left of right on what to keep, and should see what is going to be saved after the choice in a window below it.
Merging commits
I like to do this before I contribute a timeline point (commit) to the remote repository wherein it will always be visible to the rest of the team. I squash commits using
git rebase -i Head~NUMBER, where NUMBER can be replaced with how many commits in the timeline, starting from the top/latest, you want to review.-iis just so that it opens something like notepad to edit rather thanvimor default terminal editor which might not be friendly to many of us.Once there, you can choose which commit should be merged into which by labelling the ones to be merged as
sorsquashand the ones to be preserved asporpick. The ones to besquashedwill then besquashedonto thepickedones.This is also known as the history rewriting command of git
-
git cherry-pickThis behaves like the rebase above and is usually used for when something exists in a different branch (or point in history), and you want to copy it over to where you are now. It is a get out of jail card if you accidentally committed to the wrong branch
All it needs is the commit
hash, its ID in the history. All branches more or less share the same history, just well organised bygit.git cherry-pick COMMIT_HASHand you are done, you have what you wanted added to your current branch as a new commit or just delayed by conflicts that you get alerted to. The conflicts can be resolved just like therebaseones, and continued withgit cherry-pick --continue. -
git stashImagine you have changes you have to commit but you want to move to another branch so you can do a very quick test or bug fix. If you ever tried, you will know that untracked and unstaged changes will follow you silently and staged changes will prevent you from going to another branch until you abandon them or commit them.
Then
git stashcomes to your rescue. Just like that, it adds your current uncommitted changes to a queue it keeps outside of the timeline it tracks. The queue is independent of any branch and you can get back to them anytime from any branch, and even keep copies there if so desired.How do you get things back from
git stash? just rungit stash popif what you want is the last thing to have been stashed, and repeat to continue and get the next last etc. If you want to get a specific one, first usegit stash listto see what is stashed and their order, thenget stash pop@{INDEX}to just get the stash at INDEX in the stash list. You can usedropinstead ofpopto delete forever from the stashed list.I leave you to delve into anything else about
git stashin your own time. -
git logTo see the history of commits of the current branch and sibling branches as well. A good terminal will present them all nicely. This is when you will realise that git messages are important.
Why is this a get-out-of-jail card? Because you need it if you ever need to revert to a different point in the timeline or back from it, cherry-pick, and just to see whether your changes actually made to the timeline or they were lost somewhere in an unknown void.
-
git reflogThis is a log that keeps track of your interactions with
gitand where in the timeline you have been during the interactions. Very useful for travelling back in time.Imagine, you were rebasing and something went terribly wrong such as picking all the wrong changes in each conflict and deleting more, but saving all that to the timeline. Not to worry, you can travel to the point before you started the rebase by using
git reflogto find where that was and what the ID/Hash of that point in time was. -
git commit --amendI use this to merge new changes on to the last commit, rather than creating a new point in time (AKA commit), and also to change the message I gave to the last commit.
If during this process, you want to abandon the merge, you can just remove the commit message that is already there (all of it) and save. Then it will abandon the merge, and you should still have your changes as uncommitted.
-
git reset --hardDESTRUCTIVE COMMAND - it will wipe away anything you haven’t committed yet.
For resetting, or going back to an earlier commit. Usually when you have committed something by mistake.
You can specify how far back in the timeline you want to go by counting backwards from head e.g.
git reset --hard Head@3to go back to the third last commit.Be sure to do more reading on this.
-
git aliasesHelps save my fingers and brain from exhaustion and stiffness. I shorten all the commands you have seen by setting aliases for them. Examples:
, git remote update becomes git ru, git commit --amend becomes git cia, git commit -m becomes git ci, git checkout becomes git ch, git branch -m becomes git nb, git branch -a becomes git ab, git status becomes git st
Superpower commands
-
git configPerfect for swapping out git defaults with your own such as the diff tool, aliases for commands, editor tool - you don’t have to be scared of vim or vi any more, just swap in Notepad.
Anyway, I recommend the git config piece put together by Atlassian.
If you want to just have a peak at what is available, try
git config --global --editfor the global config andgit config --local --edit.
And the journey continues with git.