2020-04-01

Using Git like a Pro

I wrote a Git tutorial a while ago and share it on the GitHub. Now I would like to share it again here on my website.

To see some of my other notes, please have a look at my programming-notes.

Table of Contents

  1. Git vs GitHub vs GitLab
  2. Set up your Git
  3. Basic commands
  4. Review a repo's history
  5. Add commit to a repo
  6. Tagging, branching, merging
  7. Experiments using checkout
  8. Undoing changes
  9. Collaborating and syncing with GitLab
  10. Other useful commands
  11. Development pipeline, branching model and discussion

Appendix

A. Git Bash setup B. Cygwin setup

1. Git vs GitHub vs GitLab

Figure 1‑1: Icon of Git, Github and GitLab.

Git is a very powerful tool that every developer should be familiar with.

By far, the most widely used modern version control system in the world today is Git. Git is a mature, actively maintained open-source project originally developed in 2005 by Linus Torvalds, the famous creator of the Linux operating system kernel. A staggering number of software projects rely on Git for version control, including commercial projects as well as open-source. Atlassian.com

However, many people confuse Git with Github, GitLab, but they are not the same. Git is a free and open-source distributed version control system, a tool that you can manage your code history. Where Github and GitLab are web-based hosting services for Git repositories. With Git, you don't even need Internet access, you can work everything locally and have all version controls. To connect to GitLab and working with others, you will need Internet access. The purpose of this document is to guide readers through all the necessary elements and commands of using Git, so readers will be able to use Git confidently, and in the proper way.

More discussion about Git and Github can be found here in the Stack Overflow.

Here are some nice free tutorials you can find online too:

  1. Official Git documentation.
  2. Learn Git with Bitbucket Cloud.
  3. Udacity: Version Control with Git and How to Use Git and Github.
  4. Learn Enough Git to Be Dangerous.
  5. Try Git: Git Tutorial.

2. Set up your Git

In this chapter, you are going to set up your Git environment in Windows, Mac or Linux. In Linux and Mac, using the default terminal should be just fine. In windows, you can use Git Bash or Cygwin (See appendix A and B). After the installation, run the command which shows in Figure 2-1 and sees if you have Git installed properly.

Figure 2‑1: To see the Git version from the terminal.

Figure 2‑2: Attachment files

Figure 2‑3: git terminal setup

To make your terminal console more git-friendly, you can copy-paste the folder from attachment to your root directory, and copy the content of .bash_profile to your .bashrc or .bash_profile in the root directory too. (Figure 2-2). And after copying and pasting those files and file contents, type $ source .bashrc. Then you should see something like Figure 2-3 later when you work with git.

You should do those configuration commands below before start using git. It is also important to set up your favourite editor first so you won't get panic when annoying vi pop out later (I am sorry for vi users lol). For beginners, I will suggest using nano or other editors with GUI. (Those strings with the brown colour you should replace whatever makes sense to you. Blue are comments, don't type it in your terminal.)

- $ git config --global user.name "Git Rock"
- $ git config --global user.email "git.rock@email.com"
- $ git config --global color.ui auto
- $ git config --global merge.conflictstyle diff3
- $ git config --global core.editor "emacs -nw" # (vi is default setting)
- $ git config --list # (to see your git configurations.)

Before moving on to the next chapter, take a look at all key terms describe here.

3. Basic commands

If you would like to use git as your version control, the first thing you would have to do is to initialize the git in your project folder with git init command. After git is initialized, you will see a hidden .git folder in your directory, see Figure 3-1. This is where git store all its information about your code version. And remember, do not modify anything in this .git directory unless you know what you are doing, they are hidden for good reasons.

Figure 3‑1: list directory after before and after initialize git.

And one important thing is that try to use $ git status all the time or after each command. It always shows you some hints about what you should do when something goes wrong.

The following commands are some of the most basic commands that you will use very often, I will explain other commands later, I just list them here so you can check the most basic commands after finishing this tutorial.

- $ git init
- $ git clone https://github.com/GeneKao/udacity-build-a-portfolio-site.git
- $ git status # (Please use it all the time!)
- $ git log
- $ git add
- $ git commit
- $ git diff

4. Review a repo's history

In this chapter, you will learn how to use commands such as $ git log with different flags to see all commit history from the repo. (Tips for readers not familiar with the command line. Whenever you are in the less) command environment, which you will see ":" on the bottom-left corner, press B and space to go one page up and down. Press J and K to scroll up and down. Q to quit.)

Let's clone an existing repo to learn from professional developers. To clone this repo you can type $ git clone https://github.com/nvie/gitflow.git to make a copy of existing repo and $ cd gitflow to move to the directory.

Now you can type one of the most commonly used commands $ git log --oneline --graph --all in your terminal, this will list all the commits and branches like in Figure 4-1.

Figure 4‑1: list all commits and branches using git log --oneline --graph --all

If you want to see more about all commits you can use to $ git log --stat or $ git log --patch to show all the details. Or you can use different flags like --after, --author, --grep, -S to constrain or to filter the git information that you want. Try out all those commands and see what kind of information you will get:

- $ git log --online
- $ git log --stat
- $ git log -p, git log --patch
- $ git log --oneline --decorate --graph --all
- $ git log --after="2017-10-1"
- $ git log --after="yesterday"
- $ git log --after="2017-10-1" --before="2017-10-1"
- $ git log --author="Vincent"
- $ git log --grep="bugs"
- $ git log -- md # (check changes only for README)
- $ git log -S"Hello World" # (any file that string was modified)
- $ git show

If you would like to see more detail documentation of those optional flags type$ git log --help.

And don't forget, you can always type your command together with the SHA to print the specific commit. For example, by typing $ git show b72a395 you will see all detail commit information include the lines have been modified and line numbers, see Figure 4-2.

Figure 4‑2: git show one commit by specifying its SHA.

5. Add commit to a repo

Basically, in Figure 5-1 you can see a diagram of how Git works. Let's focus on all local Git functions first. To begin with, three major components of Git are working directory, staging index and repository. Simply speaking, working directory is where all your current files are which includes tracked, untracked and ignored files, staging index is a cache of files that you would like to commit and the repository is where all Git store all snapshots of your code.

Figure 5‑1: Diagram of Git work directory, staging index and repo

To create a commit to the repo, basically you will need to do it in two steps:

1. $ git add md #(or $ git add . to add everything under current directory.)
2. $ git commit -m "add a readme file"

What we have done here is add a file that we would like to commit and move it from working directory to staging index. Assuming we have other files still in the directory. If we do the commit now, only the change of readme file will be recorded to the repository.

By the way, it is better not to use the word "and" in the one Git commit, because normally it just makes more sense to separate tasks into two commits.

For more details, I will suggest the reader go through this online course Version Control with Git, this course explains clearly the concept of the working directory, staging index and repo. Figure 5-1 shows the summarized diagram, and useful comments are listed below. (Just ignore the stash command for now or you can try it on your own. I will explain git stash in the next edition.)

- $ git config -global core.editor emacs # (Configure your favourite editor)
- $ git add # (put them in staging index / stage files)
- $ git commit -m "your comment" # (commit staged files to repo)
- $ git diff
- $ git stash # (make your code WIP and try something else)
- $ git stash pop # (reverse the stash or git stash apply)
- $ git stash list
- $ git stash save "Add style to our site"
- $ git stash show
- $ git log --oneline --graph stash@{1}
- $ git stash branch add-stylesheetstash@{1}
- $ git stash drop stash@{1}
- $ git stash clear
  # (Set up .gitignore file)

Figure 5‑2: git stash

6. Tagging, branching, merging

When you want to create a separated development, you can create the branch. You can imagine this as actual tree branches. You store all your different development in different branches so they are separated from each other. So let's create a branch called develop by typing $ git branch develop. Then if you type $ git branch --list -all you will see all branches, and the * symbol indicates the current development branch you are at, and the default branch is master. By switching between different branches you need to type $ git checkout develop. One thing amazing is that all your files switch automatically whenever you switch between branches. By doing this, you can experiment different kinds of stuff and don't need to worry about messing up your correct code or to back up all your previous development files.

After you modify your separated development, you can use Git merge to merge one branch with another branch. Normally Git will merge it automatically unless two branches have modified the same lines, then you will have to manually fix them.

- $ git tag -a v1.0 (create)
- $ git tag -a v1.0 a87984 (create)
- $ git tag -d v1.0 (delete)
- $ git branch (check)
- $ git branch dev_frontend =git checkout -b dev_frontend
- $ git branch -d dev_frontend (delete)
- $ git checkout dev_frontend
- $ git checkout dev_frontend43s20r
- $ git checkout dev_frontendmaster
- $ git merge dev_frontend

7. Experiments using checkout

You can not only experiment with your code using different branches and switch between them by using git checkout, but also switch to your previous commit or specific files.

- $ git checkout dev\_frontend # (branch)
- $ git checkout 43s20r # (commit)
- $ git checkout 43s20rpy # (file)
- $ git checkout HEADpy # (go back)

8. Undoing changes

To modify the commit, you can type $ git commit --amend to modify the last commit. To delete commits use $ git reset , and it has three different flags. Mixed is to move the commit back to the working directory, and this is the default flag. Soft is to move commit to staging index. Hard is to move commit to trash directly, so be careful to use it. When you better not use reset on the public repo, because this will mess up other people's development. Use git revert instead, this will create a new commit to undo the previous commit.

- $ git commit --amend # (modify the last commit Don't use it in Public History)
- $ git revert 43s20r # (create a new commit to undo)
- $ git reset HEAD~1 # (Be careful! Don't use it in Public History)
- $ git reset --mixed HEAD~1 # (move to the working directory, this is the default, add and commit)
- $ git reset --soft HEAD~1 # (move to staging index, commit)
- $ git reset --hard HEAD~1 # (move to trash, deleted)

9. Collaborating and syncing with GitLab

After having some commits, you might want other people to join your development or back up the code on GitHub or GitLab. By doing this, you must set up the connection between your local repo and remote repo. To see the connection you can type $ git remote -v and use $ git remote add remote YourRemoteURL to set the connections. And $ git pull to download all the changes and $ git push origin mater to upload your repo.

More information to see GitHub documentation (GitLab is more or less the same).

- $ git remote
- $ git fetch
- $ git pull
- $ git push

10. Other useful commands

- $ git diff-tree --no-commit-id --name-only -r d51488d # (list all files changes in a commit)
- $ git ls-tree --name-only -r d51488d # (list all files in a commit)

11. Development pipeline, branching model and discussion

I will suggest using gitflow to managing your version and big software development. You can also install it on the command line so everything become so easy.

Check the official repository on GitHub:

https://github.com/nvie/gitflow

- $ git flow init
- $ git flow feature start feature/dev-gk-responsive
- $ git flow feature finish feature/dev-gk-responsive
- $ git flow feature publish feature/dev-gk-responsive
- $ git flow feature pull remote feature/dev-gk-responsive

Appendix

A. Git Bash setup

Installation procedure for using git bash as Linux VM connector:

https://git-for-windows.github.io/

Create a .profile in the home directory like:

alias q="exit"
alias dir="ls -al"
alias vm="ssh -i ~/.ssh/id_rsa_np new_user@YOUR_IP"

function cd {
    builtin cd "$@" && dir
}

# Interactive operation...
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'

# Default to human-readable figures
alias df='df -h'
alias du='du -h'

# Misc :)
alias less='less -r' # raw control characters
alias whence='type -a' # where, of a sort
alias grep='grep --color' # show differences in colour
alias egrep='egrep --color=auto' # show differences in colour
alias fgrep='fgrep --color=auto' # show differences in colour


# Some shortcuts for different directory listings
alias ls='ls -hF --color=tty' # classify files in colour
alias dir='ls --color=auto --format=vertical'
alias vdir='ls --color=auto --format=long'
alias ll='ls -l' # long list
alias la='ls -A' # all but . and ..
alias l='ls -CF' #

# Enable tab completion
source ~/.git-terminal-config/git-completion.bash

# Change command prompt
source ~/.git-terminal-config/git-prompt.sh

# colors!
red="\[\033[38;5;203m\]"
green="\[\033[38;05;38m\]"
blue="\[\033[0;34m\]"
yellow="\[\033[1;33m\]"
gray="\[\033[1;30m\]"
reset="\[\033[0m\]"

export GIT_PS1_SHOWDIRTYSTATE=1

# '\u' adds the name of the current user to the prompt
# '\$(__git_ps1)' adds git-related stuff
# '\W' adds the name of the current directory
export PS1="$red\u$yellow\$(__git_ps1)$green \W
$ $reset"
# Set Git language to English
#alias git='LANG=en_US git'
alias git='LANG=en_GB git'
# Set Git language to English
#alias git='LC_ALL=en_US git'
alias git='LC_ALL=en_GB git'

In git bash, run the following commands:

B. Cygwin setup

This is nothing to do with the Git setup. It is just how we setup the Cygwin, and with this documented you can save your time googling around.

1. First install cygwin 32 bit, because some function don't work in 64 bit.
2. Download the file from "rawgit.com/transcode-open/apt-cyg/master/apt-cyg"
3. Copy apt-cyg file to /bin in your C:\cygwin\bin
4. Run "chmod +x /bin/apt-cyg" to make sure that apt-cyg is executable.
5. $ echo 'export http_proxy=proxy:8080'>>~/.bashrc # to make sure that proxy settings.
6. $ echo 'export https_proxy=proxy:8080'>>~/.bashrc
7. Use the original package manager to install wget first.
8. Everything should be fine at this moment, try "apt-cyg install nano"
9. You can also use apt-cyg searchall to search packages.

Dependency for x please see https://x.cygwin.com/docs/ug/setup.html

To install python inside cygwin see https://github.com/h2oai/h2o-2/wiki/Installing-Python-inside-Cygwin