A few git tricks & tips

Sauvik Dolui
9 min readJun 9, 2018

--

I am not a pro using git, I am still learning from https://git-scm.com, https://stackoverflow.com/questions/tagged/git and so many others resources. A few useful commands save my hours when I am on a tight schedule to complete my projects. I would be happy if they help you too. Please comment if I have any misunderstanding using them.

init:

We all use git init , it simply creates an empty git repositiry under current directory. You can also specify the path of the target directory under which an empty git repo can be inialized. So if you want to create an empty git repo under ~/Desktop/Test , your command will be

git init ~/Desktop/Test

clone:

The same is also applicable to clone command. If you execute git clone https://github.com/sauvikdolui/SDStateTableView.git , it will clone the project under SDStateTableView directory. This is the default behaviour. Instead of that, you can also specify the path of the directory where git needs to make a clone. So, to clone in a target directory use the following command

git clone <url_of_the_repo> <path_of_the_empty_directory>

Cloning a specific branch only:

Occasionally, it is required to clone a specific branch as you just want to have a look on the code base of that branch only. In that scenario you can simply use

git clone -b <name_of_the_branch> --single-branch <url_of_the_git_repo>

diff:

To see the changes before staging, use the following commands

// Shows changes made to all files in current working tree
git diff
// Shows changes made so far on a specific file only
git diff <path_to_file>
// Shows differences made on files even when they are staged
git diff --staged

add:

We generally use git add --all to add all tracked or untracked files to the current git working tree. Here are few more usages of git add

// Adds all .swift files under current directory only
1. git add *.swift
// Adds all files under Login directory only
2. git add Login/
// Adds all .swift files under Login directory only
3. git add Login/*.swift
// Adds all .swift files from current and sub-directories
4. git add '*.swift'

config:

Working on someone else’s system:

Sometimes we need to work from someone else’s system. Before you create your own commit please configure git with the followings

git config --local user.name 'your_user_name'
git config --local user.email 'your_user_email_id'
// You also need to disable current credential helper
git config credential.helper ''

For now and onwards, whenever you will try to push your code, git will explicitly ask for username and password.

Note: Before you disable the credential helper note down it’s current value using

git config --show credential.helper
// For OS X it is file:.git/config osxkeychain

Reset credential helper using git config credential.helper 'osxkeychain' .

add & commit in a single command:

We generally add a few files (new, or modified) and after then commit them. However, we can do that using a single command only when there is not any new file.

git commit -a -m 'your commit message'

Discarding changes made on a file:

Sometimes, we do some insane changes on a file in current working directory which has not been staged yet. Use checkout to discard the changes to it.

git checkout -- <path_to_file>

Unstaging a file:

If you want to unstage a file user the following command

git reset HEAD <path to file>

Editing Last Commit Message:

git commit --amend helps you to fix your silly mistakes you made while typing your last commit message.

Discarding Commits:

The Soft Way: Keep Changes

In this process the changes made to the files after last commit are not discarded, just the commit is removed from working flow.

// Moves the added files in last commit back to staged area
git reset --soft HEAD^
// Discards last two commits and HEAD points two commits back
git reset --soft HEAD^^
// Discards last n commits and HEAD points n commits back
git reset --soft HEAD~n

The Hard Way: I don’t bother about changes

Well, this is little bit dangerous and straight forward. If we use --hard instead of option --soft the changes made to the files in subsequent commits are lost. You simple end up with message nothing to commit, working tree is clean when you use git status after using git reset --hard.

Discarding Your Last Push ( Emergency only🚨 ):

If your are drunk and have written down a few lines of your secret poem(💑) on your source file and pushed it to remote , then you might be in trouble. The following two commands delete the last push made on server.

Note: Always consult with your dev-team members before you proceed!!!!!

// Move back to one commit earlier
git reset --hard HEAD^
// Push the commit forcefully to remote
git push -f

Show me the meaning…OR origin?

You might wish to

  1. list down all the remote branches and
  2. know the mapping among local and remote branches
  3. the impact of git pull and git push on local and remote branches
  4. Sync status of each local branch with their corresponding remotes.

Then the following command

// Syntax
git remote show <remote_name>
// Example
git remote show origin

will be the best option for you. It is exactly designed for these purposes.

pull

So git remote show origin helps you to find out the map among the local and remote branches. Suppose, your local repository is mistakenly tracking a feature branch feat/backend/global_country_zip_map and recently it has received an update with a 250MB database file. You are a iOS developer, and you really don’t want to pull that 250MB .db file into your local system. You are only interested in pulling down iOS feature branch feat/ios/address_management only. So you need to pull down a single branch.

Pull down a single branch only:

// Basic Syntax
git pull <remote> <remote-branch-name>
// Example
git pull origin feat/ios/address_management

git pull: Behind the Hood

git pull is a two step process

  1. git fetch fetches the remote branches
  2. git merge FETCH-HEAD and merges the locals with the latest HEAD available for each branch.

Avoid polluting history with git pull:

If you are that serious guy who hates merge commit, you can easily add option forgit pull --rebaserather than merge using the following command.

git pull --rebase

branch:

List down all branches:

git branch -a // Shows remote and local branches
git branch // Shows only local branches

Creating and checkout into a branch:

// Syntax
git branch <branch_name>
// Creating a feature branch for address management
git branch feat/ios/address_management
// Checking into that
git checkout feat/ios/address_management
// Creating and checking in with a single line
git checkout -b feat/ios/address_management

Deleting Local Branch:

It’s a good practice to create separate branch for each single feature and once the task is completed, you merge the branch into develop and delete local feature branch.

// Syntax
git branch -d <branch>
// Deleting a local feature branch
git branch -d feat/ios/address_management

Suppose, I have atemp branch with a few changes within that which are not merged into any other main stream branch. If I want to delete that branch, gitshows me the following error

error: The branch ‘temp’ is not fully merged.
If you are sure you want to delete it, run ‘git branch -D temp’.

To delete temp forcefully execute the command with option -D

git branch -D temp

Deleting multiple local branch at the same time:

While cleaning up you local repository, deleting multiple branch can be done with the following command

git branch -d local_branch1 local_branch2 local_branch3

Deleting branch from remote:

Sometimes, we backup our feature branches by just pushing them into remotes if the task takes more than one day. Deleting these feature branches are important for cleaning up remotes.

// The basic syntax to delete a remote branch
git push <remote> :<branch_name>
// Deleting feat/ios/address_management from remote origin
git push origin :feat/ios/address_management
// Deleting multiple remote branches at once
git push origin :feat/ios/address_management :feat/deal_management

Set upstream for a local branch:

Suppose one of your existing local branch needs to be tracked with a remote one. You need to map (set up-stream) these two using the following command

git branch --set-upstream-to=origin/<branch> develop/functionality-new

push:

Pushing a single branch only:

By default when you execute git push git pushes committed changes to all remote branches which are tracked. If you wish only to publish changes made on a specific branch , the following command might be helpful.

// General syntax
git push <remote> <remote_branch>
// Example
git push bitbucket feat/ios/login_api
// Pushed local branch prod to CI server heroku branch master
git checkout prod
git push heroku master

tags:

git tags are really useful to archive code base related to a specific release version. Suppose, you are the delivery manager to finally push the code to Heroku Continuous Integration (Heroku CI) server using git push heroku master and finally deploy that using heroku open. Congratulations!!🤝🤝 your have successfully deployed v0.0.1. Wait🧐🧐, do you need a backup of this code base? Because next time when you will publish v0.0.2 and so on, it will be hard to hop from one commit to another to get the production code base for each version. Using tag s can help you a lot. So, when you deploy a version of your application, you can archive that codebase by creating a new tag.

Creating a tag:

// Basic Syntax
git tag -a <name_of_tag> -m ‘tag message’
// Example
git tag -a v0.0.1-⍺ -m 'Published v0.0.1-⍺, need to stay awake to fix any bug 😭'

Pushing tags to remote:

// Publishing all tags
git push --tags
// Publishing a single tag// Syntax
git push <remote> <tag_name>
// Example
git push bitbucket v0.0.1-⍺

List of all tags:

git tag

Checking out tag:

So, I published v0.0.1-⍺ last night, this morning appears to be good as I have received just one minor issue. Delivery manager asked to me fix that issue and finally deploy the build for beta release. So I need to

  1. Check out tag v0.0.1-⍺
  2. Create a issue fix branch fix/ios/minor_issue.
  3. Fix the issue and merge the fix into prod.
  4. Deploy the build.
  5. Create a separate beta release tag and
  6. Finally push that tag into remote.

Try to follow me on terminal

// 1. Checkout 
git checkout v0.0.1-⍺
// 2. Create fix branch
git checkout -b fix/ios/minor_issue
// 3. Fix and merge prod into fix/ios/minor_issue
git merge prod
// 4. Checkout and merge fix/ios/minor_issue into prod
git checkout prod
git merge fix/ios/minor_issue
// 5. Deploy build// 6. Create a beta release tag
git tag -a v0.0.1-β -m 'Boss! Can I sleep tonight? 🤣'
// Push Tag to remote
git push bitbucket v0.0.1-β

Deleting Tags:

The syntax are identical with the process of deleting a branch from local and remote.

// Deleting tag from local
git tag -d v0.0.1-β
// Deleting tag from remote
git push bitbucket :v0.0.1-β

Creating tag from an earlier commit:

We can even create a tag from an earlier commit. You just need specify the SHA hash of the commit, the syntax is as follows

// Syntax
git tag -a <tag_name> <SHA Hash of that commit>
// Example
git tag -a v1.2 9fceb02

remote:

List of all remotes:

git remote -v

Maintaining multiple remotes ( Bitbucket + GitHub + GitLab + …):

By default we call our sweet remote as origin . Sometimes, we continue developing features and pushing them to remote originin our company’s own repository until company get paid for delivering the codebase to client. Suppose our company has it’s own code base repository at BitBucket. Client owns his account at GitHub. Client has just paid the money, now he wants the full codebase with each single commit, someone is waiting there for code review😂. That’s becoming really tricky? No, you just need multiple remotes.

Strategy:

  1. While setting up he project, just create it at Bitbucket. Get the URL of the repo. Suppose it is https://<my_company>@bitbucket.org/sauvikdolui_apple/<my_project>.git
  2. At your project directory
// Initialize the git repo
git init
// Add your company's Bitbucket remote
git remote add bitbucket https://<my_company>@bitbucket.org/sauvikdolui_apple/<my_project>.git

3. Continue development and push to your company’s remote bitbucket .

4. When the payment comes in (🎊🎁🎉), you need to push into client’s repo.

// Add your Client's Github remote
git remote add github https://github.com/sauvikdolui/<my_project>.git

5. And you can push your development branch develop into client’s repo using

git push -u github develop 
// for the first time use option -u to set upstream

with all your commit history from the begining.

Thanks for reading the blog. If you really enjoyed the tricks and tips, please hit the clap button. I also welcome your valuable comments.

Promotions:

Don’t forget to read my previous blogs😏.

1. Network reachability status monitoring on iOS

  1. Part 1.
  2. Part 2.

2. A Smart Way to Manage Colour Schemes for iOS Application Development.

3. Handling Fonts in iOS Development, a Simpler Way.

4. Developing a Tiny Logger in Swift.

5. Making a Stateful TableView for iOS.

--

--