A few git tricks & tips
Image source https://www.atlassian.com/git/tutorials/using-branches
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 only1.
git add *.swift
// Adds all files under Login directory only2.
git add Login/
// Adds all .swift files under Login directory only3.
git add Login/*.swift
// Adds all .swift files from current and sub-directories4.
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 remotegit push -f
Show me the meaning…OR origin?
You might wish to
- list down all the remote branches and
- know the mapping among local and remote branches
- the impact of git pull and git push on local and remote branches
- 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>
// Examplegit pull origin feat/ios/address_management
git pull: Behind the Hood
git pull
is a two step process
git fetch
fetches the remote branchesgit 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
--rebase
rather 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 managementgit branch feat/ios/address_management
// Checking into thatgit checkout feat/ios/address_management
// Creating and checking in with a single linegit 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, git
shows 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 remote
s if the task takes more than one day. Deleting these feature branches are important for cleaning up remote
s.
// The basic syntax to delete a remote branch
git push <remote> :<branch_name>
// Deleting feat/ios/address_management from remote origingit 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
// Syntaxgit 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
- Check out tag v0.0.1-⍺
- Create a issue fix branch fix/ios/minor_issue.
- Fix the issue and merge the fix into
prod.
- Deploy the build.
- Create a separate beta release tag and
- 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 origin
in 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 holds 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:
- 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
- At your project directory
// Initialize the git repo
git init
// Add your company's Bitbucket remotegit remote add bitbucket https://<my_company>@bitbucket.org/sauvikdolui_apple/<my_project>.git
-
Continue development and push to your company’s remote
bitbucket
. -
When the payment comes in (🎊🎁🎉), you need to push into client’s repo.
// Add your Client's Github remotegit remote add github https://github.com/sauvikdolui/<my_project>.git
- 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😏.