Common Git Tips


Obtain list of commits

git reflog --oneline
git log --oneline

These commands will also print commit ID - a.k.a. commit hash.

Obtain list of branches created by a user

git for-each-ref --format=' %(authorname) %09 %(refname)' --sort=authorname | grep <username>

Obtain branch hash

git show-ref branch_name

Delete a local/remote branch

Assume that a branch "bugfix/114355" is created to fix a bug. To delete the local branch:

git branch -d bugfix/114355
git branch -D bugfix/114355

'-D' is same as specifying "--delete --force".

To remove the remote branch as well:

git push origin --delete bugfix/114355

Undo last commit

git reset --soft HEAD~1

Roll back repo to a commit

To roll-back the repository to a particular commit, follow these steps.

  • find the hash corresponding to the particular commit by checking the commit logs:
    git log --oneline
  • roll back the repository by resetting the HEAD pointer:
    git reset --hard <commit_hash>

Remove the latest commit entirely

If changes are staged (only "commit" is done)

git reset --hard HEAD^
git reset --hard THE_COMMIT_HASH

If changes are committed (commit and push done)

git checkout HEAD^
git commit --am 'revert'
git push

If this operation needs to be done for a specific file, add "-- filepath" to above command, like

git checkout HEAD^ -- /path/to/file

Note: "--hard" option will completely remove the changes from the staging area also, if intention is to retain those changes in staging area, use "--soft" option instead, in the above commands.

Comparison between two branches

git diff-tree -C -r branch1_hash branch2_hash

List different commits between two branches

To list all commits

git log --left-right --graph --oneline branch1...branch2

To list all commits specific to a file

git log --left-right --graph --oneline branch1...branch2 -- <fileame>

Squashing multiple commits

Warning: Doing this on the remote branch is dangerous because other developers might have pushed their changes on it and squashing would destroy their work too, so please be diligent.

It is always better to squash multiple commits made to your local branch (while implementing a feature or a bug fix), and then push the code to the remote branch. It makes commit history much cleaner and simpler to understand.

Assume that there are 4 commits done on your local branch as part of implementing a bug fix. To squash all these commits into single one, follow these steps.

git log --oneline

This will provide the short history of commits. Decide how many of these are to be squashed. Let's assume the top 4 needs to be squashed.

git rebase -i HEAD~4

In the editor window shown after this, leave the top-most "pick" as is, and change all subsequent "pick" word to "squash". Save the file and exit.

Another editor window will open, showing all the commit messages entered so far. Edit/delete the messages as per requirement. Save file and exit.

git push --force-with-lease origin HEAD

Splitting last commit into multiple commits

This is a slightly tricky situation and should be dealt with extreme care and diligence. Backup all code changes to a safe place before taking any step further. Situation is as follows:

  • Everything is in the context of developer's private bugfix branch.
  • There is a single commit made, which has gone to the remote branch. A Pull Request is also raised for this commit, but it is under review (meaning it is not cleared for further merge yet).
  • Since there are many sub-modules which have code changes, it is desirable to split the single commit into multiple commits, each corresponding to one sub-module.

This was handled using following procedure. AGAIN: BE EXTREMELY CAREFUL!

In local branch:

  • squashed all previous commits for the task into single one (please refer squashing section above).
  • pushed it to the remote branch as well.

Performed git pull to synchronize local and remote branches. Then,

git reset HEAD~
git stash push

The last command stashed all changes, which are now visible due to "git reset".

Since the commit is also on the remote branch, pushed the local changes to remote to remove the last commit from remote branch.

git push origin +HEAD^:bugfix/114355-name-of-the-branch

Make sure local and remote branches are synchronized.

git pull
git stash pop

Last command restored all changes to the local workspace.

Now, for each individual component, following commands were issued.

git add <component_specific_files>
git commit -m "message" <component_specific_files>
git push

This created multiple individual commits instead of a single one.

Rebasing a branch

To rebase feature-branch onto second-branch, using interactive mode:

git checkout feature-branch
git rebase -i second-branch
git push --force-with-lease

Excellent collection of Git commands can be found at GitHub Docs.


 

Comments

Popular posts from this blog

Security in Linux Kernel - Part 2

Trusted Platform Module