top of page

Git Tips and Tricks

Tips and tricks

Switch branches

$ git checkout <branch>

show

$ git show

Shows log message and diff about the commit you are on. blame

To see who wrote the code? For each line of the file what commit edited that line of code will be shown. So now you can use that git commit and pass it to git show <commit> to see all the changes.

$ git blame path/to/file

cherry-pick

To move a commit from one branch to another branch. Situation where: I committed to master when I meant to commit to my feature branch. I need to move my commit!

Get the commit hash

$ git show

Change to the branch you wanted to add that commit

$ git checkout <feature-branch>

Add it to the branch you are on

$ git cherry-pick <commit hash>

cherry-pick creates an entirely new commit based off the original, and it does not delete the original commit. So you will have to delete it manually. See below how to do it.

You can also get conflict during cherry-pick

$ git cherry-pick 435bedfa

Resolve the conflict and then

$ git cherry-pick --continue

reset

Remove the last commit.

$ git reset --hard HEAD^

HEAD : the commit I’m currently sitting on

HEAD^ : this commit’s parent

HEAD^^: this commit’s grandparent and so on

Rebase :

rebase is a command for changing history. Never change history when other people might be using your branch, unless they know you’re doing so. Never change history on master. Best practice: only change history for commits that have not yet been pushed.

$ git checkout master $ git pull --ff upstream master $ git checkout <feature-branch> $ git rebase master -i

While pushing need to do force push because there is change of history. Local branch and remote branch have diverged.

$ git push origin <feature-branch> -f

In case of conflicts, find the conflicting file.

$ git status

reolve those conflicts and then continue the rebase

$ git status $ git rebase --continue

Squashing commits :

Amending the commit

$ git add missing-file $ git commit --amend

Squashing

Look at last 5 commits. Below command will open the text editor.

$ git rebase --interactive HEAD~5

Once in editor, you can select which ones to squash into previous one and ones to pick as it is. Now type new commit message to squashed commits. Splitting commits

$ git rebase --i HEAD~3

Now this will open the commit history in editor. The commit you want to split, change it from pick to edit. Save that file. Git will pause in the rebase process and give us time to create new commits. The too-big commit is already present, so let’s pop it off, but keep the changes:

$ git reset HEAD^

Not using --hard because we want to have the changes we wanted. Make changes as needed. Now add individual file and commit. And continue rebase.

$ git rebase --continue

bisect

The feature’s broken? But it was working fine 2 months ago… what changes? Bisect will help you find the commit that introduced the problem.

Need commit where it was working, commit where it’s broken and a test to verify that.

$ git bisect start $ git checkout broken-commit $ git bisect bad $ git checkout working-commit $ git bisect good

Git merge from someone else’s fork

Add their github fork repo as a remote to a clone of your own repo:

$ git remote add other-guys-repo <url to other guys repo>

Get their changes:

$ git fetch other-guys-repo

Checkout the branch where you want to merge:

$ git checkout my_new_branch

Merge their changes in (assuming they did their work on the master branch):

$ git merge other-guys-repo/master

Resolve conflicts, commit the resolutions and voila. Quick Ref: http://stackoverflow.com/a/5606062 How to pull remote branch from somebody else’s repo

$ git remote add coworker git://path/to/coworkers/repo.git $ git fetch coworker $ git checkout --track coworker/foo

This will setup a local branch foo, tracking the remote branch coworker/foo. So when your coworker has made some changes, you can easily pull them:

$ git checkout foo $ git pull

Graphs

The --graph option draws an ASCII graph representing the branch structure of the commit history. This is commonly used in conjunction with the --oneline and --decorate commands to make it easier to see which commit belongs to which branch:

$ git log --graph --oneline --decorate

For a simple repository with just two branches, this will produce the following:

* 0e25143 (HEAD, master) Merge branch 'feature' |\ | * 16b36c6 Fix a bug in the new feature | * 23ad9ad Start a new feature * | ad8621a Fix a critical security issue |/ * 400e4b7 Fix typos in the documentation * 160e224 Add the initial code base

The asterisk shows which branch the commit was on, so the above graph tells us that the 23ad9ad and 16b36c6 commits are on a topic branch and the rest are on the master branch.

While this is a nice option for simple repositories, you’re probably better off with a more full-featured visualization tool like gitk or SourceTree for projects that are heavily branched.

Custom Formatting For all of your other git log formatting needs, you can use the --pretty=format:"<string>" option. This lets you display each commit however you want using printf-style placeholders.

For example, the %cn, %h and %cd characters in the following command are replaced with the committer name, abbreviated commit hash, and the committer date, respectively.

$git log --pretty=format:"%cn committed %h on %cd"

This results in the following format for each commit:

John committed 400e4b7 on Fri Jun 24 12:30:04 2014 -0500 John committed 89ab2cf on Thu Jun 23 17:09:42 2014 -0500 Mary committed 180e223 on Wed Jun 22 17:21:19 2014 -0500 John committed f12ca28 on Wed Jun 22 13:50:31 2014 -0500

The complete list of placeholders can be found in the Pretty Formats section of the git log manual page.

Aside from letting you view only the information that you’re interested in, the --pretty=format:"<string>" option is particularly useful when you’re trying to pipe git log output into another command.

Filtering the Commit History Formatting how each commit gets displayed is only half the battle of learning git log. The other half is understanding how to navigate the commit history. The rest of this article introduces some of the advanced ways to pick out specific commits in your project history using git log. All of these can be combined with any of the formatting options discussed above.

By Amount The most basic filtering option for git log is to limit the number of commits that are displayed. When you’re only interested in the last few commits, this saves you the trouble of viewing all the commits in a pager.

You can limit git log’s output by including the -<n> option. For example, the following command will display only the 3 most recent commits.

$git log -3

By Date If you’re looking for a commit from a specific time frame, you can use the --after or --before flags for filtering commits by date. These both accept a variety of date formats as a parameter. For example, the following command only shows commits that were created after July 1st, 2014 (inclusive):

$git log --after="2014-7-1"

You can also pass in relative references like "1 week ago" and "yesterday":

$get log --after="yesterday"

To search for a commits that were created between two dates, you can provide both a --before and --after date. For instance, to display all the commits added between July 1st, 2014 and July 4th, 2014, you would use the following:

$git log --after="2014-7-1" --before="2014-7-4"

Note that the --since and --until flags are synonymous with --after and --before, respectively.

By Author When you’re only looking for commits created by a particular user, use the --author flag. This accepts a regular expression, and returns all commits whose author matches that pattern. If you know exactly who you’re looking for, you can use a plain old string instead of a regular expression:

$git log --author="John"

This displays all commits whose author includes the name John. The author name doesn’t need to be an exact match—it just needs to contain the specified phrase.

You can also use regular expressions to create more complex searches. For example, the following command searches for commits by either Mary or John.

$git log --author="John\|Mary"

Note that the author’s email is also included with the author’s name, so you can use this option to search by email, too.

If your workflow separates committers from authors, the --committer flag operates in the same fashion.

By Message To filter commits by their commit message, use the --grep flag. This works just like the --author flag discussed above, but it matches against the commit message instead of the author.

For example, if your team includes relevant issue numbers in each commit message, you can use something like the following to pull out all of the commits related to that issue:

$git log --grep="JRA-224:"

You can also pass in the -i parameter to git log to make it ignore case differences while pattern matching.

By File Many times, you’re only interested in changes that happened to a particular file. To show the history related to a file, all you have to do is pass in the file path. For example, the following returns all commits that affected either the foo.py or the bar.py file:

$git log -- foo.py bar.py

The -- parameter is used to tell git log that subsequent arguments are file paths and not branch names. If there’s no chance of mixing it up with a branch, you can omit the --.

By Content It’s also possible to search for commits that introduce or remove a particular line of source code. This is called a pickaxe, and it takes the form of -S"<string>". For example, if you want to know when the string Hello, World! was added to any file in the project, you would use the following command:

$git log -S"Hello, World!"

If you want to search using a regular expression instead of a string, you can use the -G"<regex>" flag instead.

This is a very powerful debugging tool, as it lets you locate all of the commits that affect a particular line of code. It can even show you when a line was copied or moved to another file.

By Range You can pass a range of commits to git log to show only the commits contained in that range. The range is specified in the following format, where <since> and <until> are commit references:

$git log <since>..<until>

This command is particularly useful when you use branch references as the parameters. It’s a simple way to show the differences between 2 branches. Consider the following command:

$git log master..feature

The master..feature range contains all of the commits that are in the feature branch, but aren’t in the master branch. In other words, this is how far feature has progressed since it forked off of master. You can visualize this as follows:

Filtering Merge Commits By default, git log includes merge commits in its output. But, if your team has an always-merge policy (that is, you merge upstream changes into topic branches instead of rebasing the topic branch onto the upstream branch), you’ll have a lot of extraneous merge commits in your project history.

You can prevent git log from displaying these merge commits by passing the --no-merges flag:

$git log --no-merges

On the other hand, if you’re only interested in the merge commits, you can use the --merges flag:

$git log --merges

This returns all commits that have at least two parents.

Show line numbers by default with git grep command

$ git config --global grep.lineNumber true


RECENT POSTS

FEATURED POSTS

FOLLOW US

  • Grey Facebook Icon
  • Grey Twitter Icon
  • Grey Instagram Icon
  • Grey Google+ Icon
  • Grey Pinterest Icon
bottom of page