Git and Github: Key points


Command line tutorial

File compare tool from OS

Windows :- FC (File compare)
Linux/Mac :- Diff (Difference)

Git

Check git version
git --version

Git commit story

  • Each commit has an Id. For a medium sized repository, first 8 chars can be enough to uniquely identify the commit.
  • Details log command,
    git log --stat
  • Display the difference between two commits,
    git diff COMMIT_ID_1 COMMIT_ID_2
    First write source commit and then destination commit. Depending on the source and destination order, you will be displayed add/delete codes.
    Altering these two will show the same changes but in opposite order.
  • There is a difference between copy and clone. In Clone, history will be downloaded as well as content.
  • Activate colorful git bash:
    git config --global color.ui.auto
  • Checkout
  • git checkout COMMIT_ID (Checkout a commit)
    git checkout BRANCH_NAME (Checkout a branch)

Detached HEAD

Whenever you checkout a previous commit, you will be in detached HEAD state. However you can restore the head by
git checkout master (Go back to master)
git checkout BRANCH_NAME (Go back to a branch)

Essentially it means, you are looking at a commit that was not labeled with a branch name.

You can see where HEAD is points to by command,
cat .git/HEAD

Note that, git log works from current branch to the parent commit

if you checkout an earlier commit and make changes and create a new commit then the new commit is lost and will not be displayed in output, cause it’s not reachable from current branch.

You can create a branch though to retain the changes in that newly created commit,
git checkout -b new_branch_name

Git workspace

Download two files

  1. git-completion.bash
  2. git-prompt.sh

add these two files in your .bash_profile like this,

source git-completion.bash
source git-prompt.sh

Set default editor to write commit messages

If you would like to open up your favorite editor whenever you write, git commit then run the following command,
git config --global core.editor "SUBLIME_PATH -n -w"

Here we are assuming your favorite editor is Sublime and replace SUBLIME_PATH with Sublime executable file.

In general if you would like to create an alias, (i.e typing a shortcut to open up Sublime or any other editor) the follow the command in your .bash_profile file
alias subl = "SUBLIME_PATH"

Common git commands

git log
git status
git clone
git diff
git checkout
git init

Staging area

There are 3 spaces:

  1. Working directory
  2. Staging area
  3. Repository

Create a file,
Using echo "First change" > index.txt

Initialize a repo by,
Using git init

Now index.txt is in your working directory.

Using git add index.txt you can add this file to staging.
Using git add . will all files to staging.

When you commit, git takes the entire changes of staging area and make a commit to repo.

Commit message style

Type

feat: a new feature
fix: a bug fix
docs: changes to documentation
style: formatting, missing semi colons, etc; no code change
refactor: refactoring production code
test: adding tests, refactoring test; no production code change
chore: updating build tasks, package manager configs, etc; no production code change

The Subject

Subjects should be no greater than 50 characters, should begin with a capital letter and do not end with a period.

Use an imperative tone to describe what a commit does, rather than what it did. For example, use change; not changed or changes.

The Body

Not all commits are complex enough to warrant a body, therefore it is optional and only used when a commit requires a bit of explanation and context. Use the body to explain the what and why of a commit, not the how.

When writing a body, the blank line between the title and the body is required and you should limit the length of each line to no more than 72 characters.

The Footer

The footer is optional and is used to reference issue tracker IDs.

Example commit msg

	feat: Summarize changes in around 50 characters or less

	More detailed explanatory text, if necessary. Wrap it to about 72
	characters or so. In some contexts, the first line is treated as the
	subject of the commit and the rest of the text as the body. The
	blank line separating the summary from the body is critical (unless
	you omit the body entirely); various tools like `log`, `shortlog`
	and `rebase` can get confused if you run the two together.

	Explain the problem that this commit is solving. Focus on why you
	are making this change as opposed to how (the code explains that).
	Are there side effects or other unintuitive consequenses of this
	change? Here's the place to explain them.

	Further paragraphs come after blank lines.

	- Bullet points are okay, too

	- Typically a hyphen or asterisk is used for the bullet, preceded
	by a single space, with blank lines in between, but conventions
	vary here

	If you use an issue tracker, put references to them at the bottom,
	like this:

	Resolves: #123
	See also: #456, #789

Commonly used git situations

  • You can compare two commits by git diff, but there is no Id in staging and working directory. So to compare working directory with staging area use no-arg git diff like this,
  • git diff

  • To compare staging with repo
  • git diff --staged

  • Discard changes in working directory
  • git checkout -- FILENAME

  • To discard any changes in working and staging area (be very careful, you can not revert this, codes in working and staging area have not been recorded )
  • git reset --hard

  • To go back to a particular commit, by discarding all the commits after it
  • git reset --hard DESIRED_COMMIT_ID

  • To go back to a commit but keeping your working directory as it is you can use reset soft. It will make code to move to that commit but your working directory will be same as of now. So the newly made changes will be there but code is commited upto that desired commit.
  • git reset --soft DESIRED_COMMIT_ID

  • To delete changes from staging area/li>
    git rm --cached FILE_NAME

Git branches

  • Display all branches as a list
  • git branch

  • Create a branch
  • git branch BRANCH_NAME

  • Checkout a branch
  • git checkout BRANCH_NAME

  • Graphical view of branches
  • git log --graph master BRANCH_NAME

  • Graphical view of branches (shorter)
  • git log --graph --oneline master BRANCH_NAME

  • Delete a branch
  • git branch -d BRANCH_NAME

  • Display the recent commit of all branches
  • git branch -v

Merge

How git merge works!

Suppose original file content is like below,
A
B
D

Now Tarif vai made some changes
B
D
E

Tarun vai also made some changes
A
B
C
D

Now if you ask git to merge the changes how will it manage to merge?

We are certain that,
B and
D
will present in final merged version, as these both are common in all 3 versions.

However,
A will not present. Becasue, Tarif vai deliberately removed it and Tarun vai didn’t do anything. Of course you don’t want to see a line in final merged version that has been deleted explicitely.
C will be present as Tarun vai added it.
E will be present as Tarif vai added it

When you merge two branches, git essentially creates another commit, called merge commit. But you may have missed it before because of IDE or SCM GUI.

Suppose, your master branch has some new commits and you are merging a previously created branch with it. Now if you run git log, in what order the log file will be displayed?
– It will be displayed in chronological order. That means, commits log will be jumbled up as the commits have been created in different point of time.

How will it affect you?
– If you run git diff of two consecutive commits, you may experience a large number of changes. May be because they are from differnt branch and just happen to reside together because of their commit time.

How do you get the REAL changes of a commit is this situation?
– Run git show COMMIT_ID, this will display the diff of this commit to it’s immediate parent commit

Merge Conflict

Merge conflict ocurres when two persons make changes in a single line. For example,

Original file content was,
A
B
C

Tarif vai made changes in 2nd line,
A
B'
C

Tarun vai also made this his changes in 2nd line,
A
B''
C

Before proceed with Git, you need to resolve the conflict. Remember, merge and conflict resolution goes into a single commit.

Rebase

Rebase is kind of an extension of merge. You still have to do the merging but the end result will be a bit differnt. Follow the concepts,

  • From a feature branch, if you rebase to master, git rebase master then the unique commits in feature branch will be applied to one by one on the top of present day master branch.
  • After the rebase you still need to do the merging. Checkout master branch and run,
  • git merge FEATURE_BRANCH

  • Now if you try git log --oneline --graph, you should see a cleaner commit history, as if there was no branching and you just applied the changes in master directly.

Github

We learnd there are 3 spaces in local repository: Working, Staging and Repo.
In remote repository like Github there are two types of repository: Origin, Upstream (You can create more if you wish, but these two are most common)

  • You can add multiple remote repos, if there is only one repo then we usually refer it by name origin
  • Fetch and Pull could be different url. To check remote urls,
  • git remote -v

  • To push to origin follow the format git push TARGET_REPOSITORY LOCAL_REPOSITORY
  • git push origin master

Fork

Fork is a concept introduced by Github, it’s not part of Git. Gitlab might call it a different name.
Fork means to clone repository from a other’s github account to your github account

When you push to remote branch there are two branches in your local machine,

  1. origin/master
  2. master

What happens when you have changes in both local master and origin master?
– Let me introduce git fetch. Git fetch updates your local machine’s origin/master and does not touch your local master branch. So there is no chance of conflict. After that you can use git log and git diff to compare.

Now you can also merge manually or you can do the fetch and merge combined by this command
git pull origin master

For log and diff in origin/master follow the command,
git log origin/master
git diff origin/master master

You can update all yoru local copies of every branches in the origin repositry by,
git fetch origin

If git pull == git fetch + git merge, then why git pull doesn’t generate a new merge commit like we see before?
– It’s called fast-forward merges. When base commit is ancestor of the other commit then it happens and merge commit will be a redundant commit, don’t ou think?

Pull request

When creating pull request from github, make sure you are selecting correct parent and correct child and also make sure chind branch can be successfully merged with parent branch so that one can accept just by a single click. Otherwise github will disable the merge request button.

So whenever you are making a pull request you need to pull the parent branche’s latest code and resolve all conflicts and create the pull request. If you request gets rejected then,

  1. fix the issue
  2. pull again from parent branch (if there is some changes meanwhile
  3. resolve conflicts (if any)
  4. push again

if you would like to get updates from Grand parent repo (from which you made the fork) or would like to make a pull request to Grand parent repo then you need to add the Grand parent repo as upstream by convention. it will create an upstream/master in your local machine.

To add an upstream url,
git remote add upstream GIT_URL

Now the rest follows exactly same as origin, just make sure to use upstream/master instead of origin/master when you refer to upstream.

Thanks for reading!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s