diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,8 +3,57 @@
 `hit-on` uses [PVP Versioning][1].
 The changelog is available [on GitHub][2].
 
-0.0.0
-=====
+### 0.1.0.0 — Aug 3, 2019
+
+* [#85](https://github.com/kowainik/hit-on/issues/85):
+  Make `hit commit` command take the commit name from the corresponding issue
+  name, if it is currently applicable (the branch name has the info about issue
+  number)
+  (by [@vrom911](https://github.com/vrom911)).
+* [#63](https://github.com/kowainik/hit-on/issues/63),
+  [#79](https://github.com/kowainik/hit-on/issues/79),
+  [#86](https://github.com/kowainik/hit-on/issues/86):
+  Implement `hit status` command with pretty output
+  (by [@chshersh](https://github.com/chshersh)).
+* [#72](https://github.com/kowainik/hit-on/issues/72):
+  Allow `hit new` command to receive branch names as long as issue numbers
+  (by [@vrom911](https://github.com/vrom911)).
+* [#89](https://github.com/kowainik/hit-on/issues/89):
+  Add `-p|push` and `-f|force` flags to `hit commit` command
+  (by [@vrom911](https://github.com/vrom911)).
+* [#81](https://github.com/kowainik/hit-on/issues/81):
+  Implement `hit diff` command with pretty diff
+  (by [@chshersh](https://github.com/chshersh)).
+* [#67](https://github.com/kowainik/hit-on/issues/67):
+  Implement `hit stash` and `hit unstash` commands
+  (by [@chshersh](https://github.com/chshersh)).
+* [#77](https://github.com/kowainik/hit-on/issues/77):
+  Implement `hit clear` command
+  (by [@chshersh](https://github.com/chshersh)).
+* [#82](https://github.com/kowainik/hit-on/issues/82):
+  Add `--force` flag to `hit fix` command
+  (by [@vrom911](https://github.com/vrom911)).
+* [#80](https://github.com/kowainik/hit-on/issues/80):
+  Add `hit uncommit` command
+  (by [@vrom911](https://github.com/vrom911)).
+* [#69](https://github.com/kowainik/hit-on/issues/69):
+  Write autocompletion instructions
+  (by [@chshersh](https://github.com/chshersh)).
+* [#49](https://github.com/kowainik/hit-on/issues/49):
+  Configure OSX releases on Travis CI
+  (by [@chshersh](https://github.com/chshersh)).
+* [#96](https://github.com/kowainik/hit-on/issues/96):
+  Add table of all commands to README
+  (by [@vrom911](https://github.com/vrom911)).
+* [#35](https://github.com/kowainik/hit-on/issues/35):
+  Write unit tests for URL parsing functions
+  (by [@kahlil29](https://github.com/kahlil29)).
+* Bump up to GHC 8.6.5
+  (by [@chshersh](https://github.com/chshersh)).
+* Bump up to `relude-0.5.0`
+  (by [@chshersh](https://github.com/chshersh)).
+
+### 0.0.0
 
 * Initially created.
 
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,11 +1,11 @@
 # Hit On
 
 ![hit-on logo](https://user-images.githubusercontent.com/4276606/53816638-d86e4a00-3f9e-11e9-83ab-74032363292f.png)
-[![Hackage](https://img.shields.io/hackage/v/hit-on.svg)](https://hackage.haskell.org/package/hit-on)
-[![MPL-2.0 license](https://img.shields.io/badge/license-MPL--2.0-blue.svg)](LICENSE)
+[![Build status](https://img.shields.io/travis/kowainik/hit-on.svg?logo=travis)](https://travis-ci.org/kowainik/hit-on)
+[![Hackage](https://img.shields.io/hackage/v/hit-on.svg?logo=haskell)](https://hackage.haskell.org/package/hit-on)
 [![Stackage Lts](http://stackage.org/package/hit-on/badge/lts)](http://stackage.org/lts/package/hit-on)
 [![Stackage Nightly](http://stackage.org/package/hit-on/badge/nightly)](http://stackage.org/nightly/package/hit-on)
-[![Build status](https://secure.travis-ci.org/kowainik/hit-on.svg)](https://travis-ci.org/kowainik/hit-on)
+[![MPL-2.0 license](https://img.shields.io/badge/license-MPL--2.0-blue.svg)](LICENSE)
 
 **Kowainik Git Workflow Helper Tool.**
 
@@ -17,15 +17,28 @@
 
 Here is an example of how you can see the list of issues and the issue description with `hit`:
 
-![Screenshot from 2019-03-17 00-21-23](https://user-images.githubusercontent.com/8126674/54478225-cae07c00-484a-11e9-86b3-c4c54e281274.png)
+![hit issue](https://user-images.githubusercontent.com/8126674/54478225-cae07c00-484a-11e9-86b3-c4c54e281274.png)
 
+Or how you can see pretty short stats about your changes:
+
+![hit status example](https://user-images.githubusercontent.com/4276606/60981099-428d6600-a368-11e9-97aa-656a3dd38efa.png)
+
 ## Getting started
 
 ### Prerequisites
 
 To start using `hit` make sure that you have the following tools installed on your machine:
 
-* [ `git`][git] — `hit` is a wrapper around `git`
++ [ `git`][git] — `hit` is a wrapper around `git`
++ **Optional:** `diff-highlight` — for pretty output of the `hit diff` command
+  + Linux installation instructions
+    ```shell
+    cd /usr/share/doc/git/contrib/diff-highlight/
+    sudo make
+    sudo chmod +x diff-highlight
+    sudo ln -s diff-highlight /usr/local/bin/diff-highlight
+    ```
+  + [macOS installation instructions](https://www.viget.com/articles/dress-up-your-git-diffs-with-word-level-highlights/)
 
 ### Installation
 
@@ -89,11 +102,16 @@
 
 Follow the steps below to configure `hit` :
 
-1. Specify your GitHub login in the global `.gitconfig`
+1. Enable autocompletion by calling the following command:
+    ```shell
+    source <(hit --bash-completion-script `which hit`)
+    ```
+    Add it your personal config file (like `~/.bashrc`) to enable automatically.
+2. Specify your GitHub login in the global `.gitconfig`
 ```shell
 git config --global user.login <your_login>
 ```
-2. **This step is only required if you want to use `hit` with private repositories**.
+3. **This step is only required if you want to use `hit` with private repositories**.
     1. [Create OAuth token on GitHub.](https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/) The following scopes for the token should be specified:
     ![Screenshot from 2019-03-16 22-34-57](https://user-images.githubusercontent.com/4276606/54476778-30793c00-483c-11e9-9625-a4f6ced40820.png)
 
@@ -103,6 +121,29 @@
         export GITHUB_TOKEN=<paste_generated_token_here>
         ```
 
+## Commands
+
+ | Command  | Description                                                                |
+ |----------|----------------------------------------------------------------------------|
+ | hop      | Switch to branch and sync it                                               |
+ | fresh    | Rebase current branch on remote one                                        |
+ | new      | Create new branch from the current one                                     |
+ | stash    | Stash all local changes                                                    |
+ | unstash  | Unstash previously stashed changes                                         |
+ | commit   | Commit all local changes and prepend issue number                          |
+ | uncommit | Reset to the previous commit saving the changes                            |
+ | fix      | Fix requested changes to the last commit                                   |
+ | amend    | Amend changes to the last commit and force push                            |
+ | issue    | Show the information about the issue                                       |
+ | push     | Push the current branch                                                    |
+ | sync     | Sync local branch with its remote                                          |
+ | resolve  | Switch to master, sync and delete the branch                               |
+ | clear    | Remove all local changes permanently                                       |
+ | current  | Show info about current branch and issue (if applicable)                   |
+ | status   | Show current branch and beautiful stats with COMMIT_HASH (by default HEAD) |
+ | diff     | Display beautiful diff with COMMIT_HASH (by default HEAD)                  |
+ | clone    | Clone the repo. Use 'reponame' or 'username/reponame' formats              |
+
 ## Usage
 
 The best way to demonstrate the power of the `hit` tool on a day-to-day basis with our workflow is to go through the entire workflow step by step, solving an ordinary problem of the typical [`git`][git] user.
@@ -174,6 +215,28 @@
 
 It uses the issue title to generate a short description.
 
+### hit status
+
+Before commiting your changes, you may want to inspect short stats about your
+work. With `git` you usually call the following command:
+
+```shell
+git status
+```
+
+However, the same `hit` command produces better output:
+
+```shell
+hit status
+```
+
+![hit status example](https://user-images.githubusercontent.com/4276606/60981099-428d6600-a368-11e9-97aa-656a3dd38efa.png)
+
+### hit diff
+
+If you want to see detailed diff of your changes, use `hit diff` command. If you
+have `diff-hightlight` installed then `hit diff` outputs much nicer diffs.
+
 ### hit commit
 
 After finishing your work on that issue, you need to commit your changes. With `git` you would do the following:
@@ -191,6 +254,15 @@
 hit commit "Implement my feature"
 ```
 
+or even simplier:
+
+```shell
+hit commit
+```
+
+And the commit name would be the title of the corresponding issue at GitHub (if
+you are currently in the branch named as described above).
+
 Note that you don't need to keep in mind the current issue number. However, if you want to refresh the context about the issue, use the `hit current` command.
 
 ### hit push
@@ -208,6 +280,12 @@
 ```shell
 hit push
 ```
+
+> __Note:__ `hit push` command can be combined with the `hit commit` command
+> using `-p|push` flag in the latter command.
+> ```shell
+> hit commit --push
+> ```
 
 ### hit sync
 
diff --git a/hit-on.cabal b/hit-on.cabal
--- a/hit-on.cabal
+++ b/hit-on.cabal
@@ -1,47 +1,26 @@
-cabal-version:       2.0
+cabal-version:       2.4
 name:                hit-on
-version:             0.0.0
+version:             0.1.0.0
 synopsis:            Haskell Git Helper Tool
 description:         Haskell Git Helper Tool
 homepage:            https://github.com/kowainik/hit-on
 bug-reports:         https://github.com/kowainik/hit-on/issues
 license:             MPL-2.0
 license-file:        LICENSE
-author:              Kowainik
-maintainer:          xrom.xkov@gmail.com
+author:              Veronika Romashkina, Dmitrii Kovanikov
+maintainer:          Kowainik <xrom.xkov@gmail.com>
 copyright:           2019 Kowainik
 category:            Git, CLI Tool
 build-type:          Simple
 extra-doc-files:     README.md
                    , CHANGELOG.md
-tested-with:         GHC == 8.6.3
+tested-with:         GHC == 8.6.5
 
 source-repository head
   type:                git
   location:            https://github.com/kowainik/hit-on.git
 
-library
-  hs-source-dirs:      src
-  exposed-modules:     Hit
-                         Hit.Cli
-                         Hit.ColorTerminal
-                         Hit.Git
-                         Hit.Issue
-
-  autogen-modules:     Paths_hit_on
-  other-modules:       Paths_hit_on
-                       Prelude
-
-  build-depends:       base-noprelude ^>= 4.12.0.0
-                     , ansi-terminal >= 0.8
-                     , github ^>= 0.20
-                     , gitrev ^>= 1.3
-                     , optparse-applicative ^>= 0.14
-                     , relude ^>= 0.4
-                     , shellmet >= 0.0.0
-                     , text
-                     , vector ^>= 0.12
-
+common common-options
   ghc-options:         -Wall
                        -Wincomplete-uni-patterns
                        -Wincomplete-record-updates
@@ -67,7 +46,35 @@
                        TypeApplications
                        ViewPatterns
 
+library
+  import:              common-options
+  hs-source-dirs:      src
+  exposed-modules:     Hit
+                         Hit.Cli
+                         Hit.ColorTerminal
+                         Hit.Core
+                         Hit.Git
+                           Hit.Git.Status
+                         Hit.Issue
+
+  autogen-modules:     Paths_hit_on
+  other-modules:       Paths_hit_on
+                       Prelude
+
+  build-depends:       base-noprelude ^>= 4.12.0.0
+                     , ansi-terminal >= 0.8
+                     , directory ^>= 1.3
+                     , github ^>= 0.20
+                     , gitrev ^>= 1.3
+                     , optparse-applicative ^>= 0.14
+                     , process ^>= 1.6
+                     , relude ^>= 0.5
+                     , shellmet >= 0.0.0
+                     , text
+                     , vector ^>= 0.12
+
 executable hit
+  import:              common-options
   hs-source-dirs:      app
   main-is:             Main.hs
 
@@ -78,26 +85,20 @@
                        -threaded
                        -rtsopts
                        -with-rtsopts=-N
-                       -Wincomplete-uni-patterns
-                       -Wincomplete-record-updates
-                       -Wcompat
-                       -Widentities
-                       -Wredundant-constraints
-                       -fhide-source-paths
-                       -Wmissing-export-lists
-                       -Wpartial-fields
 
-  default-language:    Haskell2010
-  default-extensions:  ConstraintKinds
-                       DeriveGeneric
-                       GeneralizedNewtypeDeriving
-                       InstanceSigs
-                       KindSignatures
-                       LambdaCase
-                       OverloadedStrings
-                       RecordWildCards
-                       ScopedTypeVariables
-                       StandaloneDeriving
-                       TupleSections
-                       TypeApplications
-                       ViewPatterns
+
+test-suite hit-on-test
+  import:              common-options
+  type:                exitcode-stdio-1.0
+  hs-source-dirs:      test
+  main-is:             Main.hs
+
+  build-depends:       base
+                     , text
+                     , hspec
+                     , github
+                     , hit-on
+
+  ghc-options:        -threaded
+                      -rtsopts
+                      -with-rtsopts=-N
diff --git a/src/Hit/Cli.hs b/src/Hit/Cli.hs
--- a/src/Hit/Cli.hs
+++ b/src/Hit/Cli.hs
@@ -9,13 +9,15 @@
 
 import Data.Version (showVersion)
 import Development.GitRev (gitCommitDate, gitDirty, gitHash)
-import Options.Applicative (Parser, ParserInfo, argument, auto, command, execParser, fullDesc, help,
-                            helper, info, infoOption, long, metavar, progDesc, short, strArgument,
-                            subparser, switch)
+import Options.Applicative (CommandFields, Mod, Parser, ParserInfo, argument, auto, command,
+                            execParser, flag, fullDesc, help, helper, info, infoOption, long,
+                            metavar, progDesc, short, strArgument, subparser, switch)
 
 import Hit.ColorTerminal (arrow, blueCode, boldCode, redCode, resetCode)
-import Hit.Git (getUsername, runAmend, runClone, runCommit, runCurrent, runFix, runFresh, runHop,
-                runNew, runPush, runResolve, runSync)
+import Hit.Core (CommitOptions (..), PushBool (..))
+import Hit.Git (getUsername, runAmend, runClear, runClone, runCommit, runCurrent, runDiff, runFix,
+                runFresh, runHop, runNew, runPush, runResolve, runStash, runStatus, runSync,
+                runUncommit, runUnstash)
 import Hit.Issue (runIssue)
 
 import qualified Data.Text as T
@@ -30,13 +32,19 @@
     Issue issueNum me -> if me
         then getUsername >>= runIssue issueNum . Just
         else runIssue issueNum Nothing
-    Commit message noIssue -> runCommit message noIssue
-    Fix message -> runFix message
+    Stash -> runStash
+    Unstash -> runUnstash
+    Commit opts -> runCommit opts
+    Uncommit -> runUncommit
+    Fix message pushBool -> runFix message pushBool
     Amend -> runAmend
     Resolve branchName -> runResolve branchName
     Push isForce -> runPush isForce
     Sync -> runSync
+    Clear isForce -> runClear isForce
     Current -> runCurrent >>= flip whenJust (flip runIssue Nothing . Just)
+    Status commit -> runCurrent >> runStatus commit
+    Diff commit -> runDiff commit
     Clone name -> runClone name
 
 ----------------------------------------------------------------------------
@@ -52,32 +60,49 @@
 data HitCommand
     = Hop (Maybe Text)
     | Fresh (Maybe Text)
-    | New Int
+    | New Text
     | Issue (Maybe Int) Bool
-    | Commit Text Bool
-    | Fix (Maybe Text)
+    | Stash
+    | Unstash
+    | Commit CommitOptions
+    | Uncommit
+    | Fix
+        (Maybe Text)  -- ^ Text of the fix commit
+        PushBool      -- ^ Force push
     | Amend
     | Resolve (Maybe Text)
-    | Push Bool
+    | Push PushBool
     | Sync
+    | Clear PushBool
     | Current
+    | Status (Maybe Text)
+    | Diff (Maybe Text)
     | Clone Text
 
 -- | Commands parser.
 hitP :: Parser HitCommand
 hitP = subparser
-    $ command "hop"     (info (helper <*> hopP)     $ progDesc "Switch to branch and sync it")
-   <> command "fresh"   (info (helper <*> freshP)   $ progDesc "Rebase current branch on remote one")
-   <> command "new"     (info (helper <*> newP)     $ progDesc "Create new branch from current one")
-   <> command "commit"  (info (helper <*> commitP)  $ progDesc "Commit all local changes and prepend issue number")
-   <> command "fix"     (info (helper <*> fixP)     $ progDesc "Fix requested changes to the last commit")
-   <> command "amend"   (info (helper <*> amendP)   $ progDesc "Amend changes to the last commit and force push")
-   <> command "issue"   (info (helper <*> issueP)   $ progDesc "Show the information about the issue")
-   <> command "push"    (info (helper <*> pushP)    $ progDesc "Push the current branch")
-   <> command "sync"    (info (helper <*> syncP)    $ progDesc "Sync local branch with its remote")
-   <> command "resolve" (info (helper <*> resolveP) $ progDesc "Switch to master, sync and delete the branch")
-   <> command "current" (info (helper <*> currentP) $ progDesc "Show info about current branch and issue (if applicable)")
-   <> command "clone"   (info (helper <*> cloneP)   $ progDesc "Clone the repo. Use 'reponame' or 'username/reponame' formats")
+    $ com "hop"      hopP      "Switch to branch and sync it"
+   <> com "fresh"    freshP    "Rebase current branch on remote one"
+   <> com "new"      newP      "Create new branch from the current one"
+   <> com "stash"    stashP    "Stash all local changes"
+   <> com "unstash"  unstashP  "Unstash previously stashed changes"
+   <> com "commit"   commitP   "Commit all local changes and prepend issue number"
+   <> com "uncommit" uncommitP "Reset to the previous commit saving the changes"
+   <> com "fix"      fixP      "Fix requested changes to the last commit"
+   <> com "amend"    amendP    "Amend changes to the last commit and force push"
+   <> com "issue"    issueP    "Show the information about the issue"
+   <> com "push"     pushP     "Push the current branch"
+   <> com "sync"     syncP     "Sync local branch with its remote"
+   <> com "resolve"  resolveP  "Switch to master, sync and delete the branch"
+   <> com "clear"    clearP    "Remove all local changes permanently"
+   <> com "current"  currentP  "Show info about current branch and issue (if applicable)"
+   <> com "status"   statusP   "Show current branch and beautiful stats with COMMIT_HASH (by default HEAD)"
+   <> com "diff"     diffP     "Display beautiful diff with COMMIT_HASH (by default HEAD)"
+   <> com "clone"    cloneP    "Clone the repo. Use 'reponame' or 'username/reponame' formats"
+  where
+    com :: String -> Parser HitCommand -> String -> Mod CommandFields HitCommand
+    com name p desc = command name (info (helper <*> p) $ progDesc desc)
 
 hopP :: Parser HitCommand
 hopP = Hop <$> maybeBranchP
@@ -86,7 +111,7 @@
 freshP = Fresh <$> maybeBranchP
 
 newP :: Parser HitCommand
-newP = New <$> issueNumP
+newP = New <$> strArgument (metavar "ISSUE_NUMBER_OR_BRANCH_NAME")
 
 issueP :: Parser HitCommand
 issueP = do
@@ -97,34 +122,57 @@
        <> help "Assigned to me"
     pure $ Issue num me
 
+stashP :: Parser HitCommand
+stashP = pure Stash
+
+unstashP :: Parser HitCommand
+unstashP = pure Unstash
+
 commitP :: Parser HitCommand
 commitP = do
-    msg <- strArgument (metavar "COMMIT_MESSAGE")
-    noIssue <- switch
+    coName <- optional $ strArgument (metavar "COMMIT_MESSAGE")
+    coNoIssueNumber <- switch
         $ long "no-issue"
        <> short 'n'
        <> help "Do not add [#ISSUE_NUMBER] prefix when specified"
-    pure $ Commit msg noIssue
+    coPush <- switch
+        $ long "push"
+       <> short 'p'
+       <> help "Push current branch with this commit"
+    coIsForcePush <- pushBoolP
+    pure $ Commit CommitOptions{..}
 
+uncommitP :: Parser HitCommand
+uncommitP = pure Uncommit
+
+{- HLINT ignore "Use <$>"-}
 fixP :: Parser HitCommand
-fixP = Fix <$> commitMessageP
+fixP = do
+    commitMsg <- commitMessageP
+    isForce   <- pushBoolP
+    pure $ Fix commitMsg isForce
 
 amendP :: Parser HitCommand
 amendP = pure Amend
 
 pushP :: Parser HitCommand
-pushP = Push <$> switch
-    ( long "force"
-   <> short 'f'
-   <> help "Force push"
-    )
+pushP = Push <$> pushBoolP
 
 syncP :: Parser HitCommand
 syncP = pure Sync
 
+clearP :: Parser HitCommand
+clearP = Clear <$> pushBoolP
+
 currentP :: Parser HitCommand
 currentP = pure Current
 
+statusP :: Parser HitCommand
+statusP = Status <$> maybeCommitP
+
+diffP :: Parser HitCommand
+diffP = Diff <$> maybeCommitP
+
 resolveP :: Parser HitCommand
 resolveP = Resolve <$> maybeBranchP
 
@@ -133,11 +181,23 @@
 
 -- | Parse optional branch name as an argument.
 maybeBranchP :: Parser (Maybe Text)
-maybeBranchP = optional $ strArgument (metavar "BRANCH_NAME")
+maybeBranchP = optional $ strArgument $ metavar "BRANCH_NAME"
 
--- / Parse optional commit message as an argument
+-- | Parse optional commit hash as an argument.
+maybeCommitP :: Parser (Maybe Text)
+maybeCommitP = optional $ strArgument $ metavar "COMMIT_HASH"
+
+-- | Parse optional commit message as an argument
 commitMessageP :: Parser (Maybe Text)
-commitMessageP = optional $ strArgument (metavar "COMMIT_MESSAGE")
+commitMessageP = optional $ strArgument $ metavar "COMMIT_MESSAGE"
+
+-- | Parse flag of force push.
+pushBoolP :: Parser PushBool
+pushBoolP = flag Simple Force
+    ( long "force"
+   <> short 'f'
+   <> help "Force push"
+    )
 
 -- | Parse issue number as an argument.
 issueNumP :: Parser Int
diff --git a/src/Hit/ColorTerminal.hs b/src/Hit/ColorTerminal.hs
--- a/src/Hit/ColorTerminal.hs
+++ b/src/Hit/ColorTerminal.hs
@@ -4,17 +4,11 @@
        ( Color (..)
        , putStrFlush
        , beautyPrint
-       , boldCode
-       , blueCode
-       , blueBg
        , bold
        , boldText
        , boldDefault
-       , greenCode
        , italic
-       , redCode
        , reset
-       , resetCode
        , setColor
        , successMessage
        , warningMessage
@@ -22,6 +16,23 @@
        , infoMessage
        , skipMessage
 
+         -- * Colors
+       , redCode
+       , blueCode
+       , greenCode
+       , yellowCode
+       , cyanCode
+       , magentaCode
+
+         -- * Other formatters
+       , boldCode
+       , resetCode
+       , blueBg
+
+         -- * Input with prompt
+       , Answer (..)
+       , prompt
+
        , arrow
        ) where
 
@@ -30,7 +41,9 @@
                             SGR (..), setSGR, setSGRCode)
 import System.IO (hFlush)
 
+import qualified Data.Text as T
 
+
 -- | Explicit flush ensures prompt messages are in the correct order on all systems.
 putStrFlush :: Text -> IO ()
 putStrFlush msg = do
@@ -79,14 +92,42 @@
 infoMessage    = colorMessage Blue
 skipMessage    = colorMessage Cyan
 
-blueCode, greenCode, boldCode, redCode, resetCode, blueBg :: Text
-redCode   = toText $ setSGRCode [SetColor Foreground Vivid Red]
-blueCode  = toText $ setSGRCode [SetColor Foreground Vivid Blue]
-greenCode = toText $ setSGRCode [SetColor Foreground Vivid Green]
-boldCode  = toText $ setSGRCode [SetConsoleIntensity BoldIntensity]
-resetCode = toText $ setSGRCode [Reset]
-blueBg    = toText $ setSGRCode [SetColor Foreground Dull White, SetColor Background Dull Blue]
+redCode, blueCode, greenCode, yellowCode, cyanCode, magentaCode :: Text
+redCode     = mkColor Red
+blueCode    = mkColor Blue
+greenCode   = mkColor Green
+yellowCode  = mkColor Yellow
+cyanCode    = mkColor Cyan
+magentaCode = mkColor Magenta
 
+boldCode, resetCode, blueBg :: Text
+boldCode   = toText $ setSGRCode [SetConsoleIntensity BoldIntensity]
+resetCode  = toText $ setSGRCode [Reset]
+blueBg     = toText $ setSGRCode [SetColor Foreground Dull White, SetColor Background Dull Blue]
+
+mkColor :: Color -> Text
+mkColor color = toText $ setSGRCode [SetColor Foreground Vivid color]
+
 -- | Arrow symbol
 arrow :: Text
-arrow = " ➤ "
+arrow = " ➤  "
+
+-- | Represents a user's answer
+data Answer = Y | N
+
+-- | Parse an answer to 'Answer'
+yesOrNo :: Text -> Maybe Answer
+yesOrNo (T.toLower -> answer )
+    | T.null answer = Just Y
+    | answer `elem` ["yes", "y", "ys"] = Just Y
+    | answer `elem` ["no", "n"]  = Just N
+    | otherwise = Nothing
+
+prompt :: IO Answer
+prompt = do
+    answer <- yesOrNo . T.strip <$> getLine
+    case answer of
+        Just ans -> pure ans
+        Nothing -> do
+           errorMessage "This wasn't a valid choice."
+           prompt
diff --git a/src/Hit/Core.hs b/src/Hit/Core.hs
new file mode 100644
--- /dev/null
+++ b/src/Hit/Core.hs
@@ -0,0 +1,28 @@
+{- | This module contains core data types used in the package.
+-}
+
+module Hit.Core
+       ( PushBool (..)
+       , CommitOptions (..)
+       ) where
+
+
+-- | Data type to represent the type of @push@: force-push or not.
+data PushBool
+    = Simple
+    | Force
+    deriving (Show, Eq)
+
+-- | Options of the @hit commit@ command.
+data CommitOptions = CommitOptions
+    { {- | Commit name. If not specified use the issue name.
+        If issue number is not applicable do not perform any actions.
+        -}
+      coName          :: !(Maybe Text)
+      -- | Do not use the issue num in the commit name.
+    , coNoIssueNumber :: !Bool
+      -- | Push immediately.
+    , coPush          :: !Bool
+      -- | Use Force push?
+    , coIsForcePush   :: !PushBool
+    }
diff --git a/src/Hit/Git.hs b/src/Hit/Git.hs
--- a/src/Hit/Git.hs
+++ b/src/Hit/Git.hs
@@ -8,20 +8,32 @@
        , runNew
        , runPush
        , runResolve
+       , runStash
+       , runUnstash
        , runCommit
+       , runUncommit
        , runFix
        , runAmend
        , runSync
+       , runClear
        , runCurrent
+       , runStatus
+       , runDiff
        , runClone
 
        , getUsername
        ) where
 
+import Control.Exception (bracket)
 import Data.Char (isAlphaNum, isDigit, isSpace)
 import Shellmet (($|))
+import System.Directory (findExecutable)
+import System.Process (callCommand)
 
-import Hit.ColorTerminal (arrow, errorMessage, greenCode, resetCode)
+import Hit.ColorTerminal (Answer (..), arrow, boldCode, errorMessage, greenCode, infoMessage,
+                          prompt, resetCode)
+import Hit.Core (CommitOptions (..), PushBool (..))
+import Hit.Git.Status (showPrettyDiff)
 import Hit.Issue (getIssueTitle, mkIssueId)
 
 import qualified Data.Text as T
@@ -40,13 +52,15 @@
     "git" ["rebase", "origin/" <> branch]
 
 -- | @hit new@ command.
-runNew :: Int -> IO ()
-runNew issueNum = do
+runNew :: Text -> IO ()
+runNew issueOrName = do
     login <- getUsername
-    let issueId = mkIssueId issueNum
-    issueTitle <- getIssueTitle issueId
-    let shortDesc = mkShortDesc issueTitle
-    let branchName = login <> "/" <> show issueNum <> "-" <> shortDesc
+    title <- case readMaybe @Int $ toString issueOrName of
+        Just issueNum -> do
+            issueTitle <- getIssueTitle $ mkIssueId issueNum
+            pure $ show issueNum <> "-" <> mkShortDesc issueTitle
+        Nothing -> pure $ mkShortDesc issueOrName
+    let branchName = login <> "/" <> title
     "git" ["checkout", "-b", branchName]
   where
     mkShortDesc :: Text -> Text
@@ -54,51 +68,90 @@
           T.intercalate "-"
         . take 5
         . words
-        . T.filter (\c -> isAlphaNum c || isDigit c || isSpace c)
+        . T.filter (\c -> isAlphaNum c
+                       || isDigit c
+                       || isSpace c
+                       || c `elem` ("_-./" :: String)
+                   )
 
 -- | @hit commit@ command.
-runCommit :: Text -> Bool -> IO ()
-runCommit (T.strip -> msg) (not -> hasIssue)
-    | msg == "" = errorMessage "Commit message cannot be empty"
-    | otherwise = do
-        branch <- getCurrentBranch
-        let issueNum = issueFromBranch branch
-        "git" ["add", "."]
-        "git" ["commit", "-m", showMsg $ guard hasIssue *> issueNum]
+runCommit :: CommitOptions -> IO ()
+runCommit CommitOptions{..} = case coName of
+    Just (T.strip -> msg)
+        | msg == "" -> errorMessage "Commit message cannot be empty"
+        | otherwise -> getCurrentIssue >>= commitCmds msg
+    {- if the commit name is not specified then check the branchName
+    If this is issue-related branch, take the issue name as the commit name.
+    Otherwise print errorMessage.
+    -}
+    Nothing -> do
+        issueNum <- getCurrentIssue
+        case issueNum of
+            Nothing -> errorMessage "Commit message cannot be empty: can not be taken from the context"
+            Just n -> do
+                title <- getIssueTitle (mkIssueId n)
+                commitCmds title issueNum
   where
-    showMsg :: Maybe Int -> Text
-    showMsg = \case
+    commitCmds :: Text -> Maybe Int -> IO ()
+    commitCmds msg issueNum = do
+        "git" ["add", "."]
+        "git" ["commit", "-m", showMsg msg $ guard hasIssue *> issueNum]
+        when (coPush || coIsForcePush == Force) $ runPush coIsForcePush
+
+    getCurrentIssue :: IO (Maybe Int)
+    getCurrentIssue = issueFromBranch <$> getCurrentBranch
+
+    showMsg :: Text -> Maybe Int -> Text
+    showMsg msg = \case
        Nothing -> msg
        Just n  ->
            let issue = "#" <> show n
            in "[" <> issue <> "] " <> msg <> "\n\nResolves " <> issue
 
--- / @hit fix@ command
-runFix :: Maybe Text -> IO ()
-runFix msg = do
+    hasIssue :: Bool
+    hasIssue = not coNoIssueNumber
+
+-- | @hit uncommit@ command
+runUncommit :: IO ()
+runUncommit = "git" ["reset", "HEAD~1"]
+
+-- | @hit fix@ command
+runFix :: Maybe Text -> PushBool -> IO ()
+runFix msg pushBool = do
     "git" ["add", "."]
     "git" ["commit", "-m", message]
-    runPush False
-    where
-        message = fromMaybe "Fix after review" msg
+    runPush pushBool
+  where
+    message :: Text
+    message = fromMaybe "Fix" msg
 
+-- | @hit stash@ command: save all local changes to stash.
+runStash :: IO ()
+runStash = do
+    "git" ["add", "."]
+    "git" ["stash"]
 
+-- | @hit unstash@ command: pop all saved changes.
+runUnstash :: IO ()
+runUnstash = "git" ["stash", "pop"]
+
 -- | @hit amend@ command.
 runAmend :: IO ()
 runAmend = do
     "git" ["add", "."]
     "git" ["commit", "--amend", "--no-edit"]
-    runPush True
+    runPush Force
 
 -- | @hit push@ command.
-runPush :: Bool -> IO ()
+runPush :: PushBool -> IO ()
 runPush isForce = getCurrentBranch >>= \branch ->
     "git" $ ["push", "--set-upstream", "origin", branch]
-         ++ ["--force" | isForce]
+         ++ ["--force" | isForce == Force]
 
 -- | @hit sync@ command.
 runSync :: IO ()
-runSync = getCurrentBranch >>= \branch -> "git" ["pull", "--rebase", "origin", branch]
+runSync = getCurrentBranch >>= \branch ->
+    "git" ["pull", "--rebase", "origin", branch]
 
 -- | @hit resolve@ command.
 runResolve :: Maybe Text -> IO ()
@@ -107,6 +160,25 @@
     runHop $ Just master
     when (curBranch /= master) $ "git" ["branch", "-D", curBranch]
 
+-- | Remove all local changes permanently.
+runClear :: PushBool -> IO ()
+runClear = \case
+    Force  -> clearChanges
+    Simple -> do
+        putText $ unlines
+            [ "This command permanently deletes all uncommited changes"
+            , "Hint: if you want to save changes, use 'hit stash' command."
+            , "Are you sure you want to delete changes? " <> boldCode <> "[y]" <> resetCode <> "/n"
+            ]
+        prompt >>= \case
+            N -> infoMessage "Aborting local clean up"
+            Y -> clearChanges
+  where
+    clearChanges :: IO ()
+    clearChanges = do
+        "git" ["add", "."]
+        "git" ["reset", "--hard"]
+
 {- | Part of the @hit current@ command. Prints the current branch and returns
 the current issue number if possible.
 -}
@@ -116,6 +188,22 @@
     putTextLn $ arrow <> "Current branch: " <> greenCode <> branchName <> resetCode
     pure $ issueFromBranch branchName
 
+{- | Show stats from the given commit. If commit is not specified, uses HEAD.
+-}
+runStatus :: Maybe Text -> IO ()
+runStatus (fromMaybe "HEAD" -> commit) = withUntrackedFiles $ showPrettyDiff commit
+
+{- | Show diff from the given commit. If commit is not specified, uses HEAD.
+This commands checks whether @diff-hightligh@ is on path and if not, just calls
+@git diff@.
+-}
+runDiff :: Maybe Text -> IO ()
+runDiff (fromMaybe "HEAD" -> commit) = withUntrackedFiles $
+    findExecutable "diff-highlight" >>= \case
+        Nothing -> "git" ["diff", commit]
+        Just _  -> callCommand $ toString $
+            "git diff " <> commit <> " --color=always | diff-highlight | less -rFX"
+
 {- | @hit clone@ command receives the name of the repo in the following
 formats:
 
@@ -151,7 +239,6 @@
         then errorMessage "user.login is not specified" >> exitFailure
         else pure login
 
-
 nameOrMaster :: Maybe Text -> Text
 nameOrMaster = fromMaybe "master"
 
@@ -172,3 +259,23 @@
     . T.takeWhile isDigit
     . T.drop 1
     . T.dropWhile (/= '/')
+
+{- | Perform given action by adding all untracked files to index and returning
+them back after action.
+-}
+withUntrackedFiles :: IO a -> IO a
+withUntrackedFiles action = bracket
+    addUntrackedFiles
+    removeUntrackedFiles
+    (const  action)
+  where
+    -- Add all untracked file to index so they will appear in diff
+    addUntrackedFiles :: IO [Text]
+    addUntrackedFiles = do
+        untrackedFiles <- lines <$> "git" $| ["ls-files", "--others", "--exclude-standard"]
+        for_ untrackedFiles $ \file -> void $ "git" $| ["add", file]
+        pure untrackedFiles
+
+    -- Return untracked files back to not spoil git state and have unexpected behavior
+    removeUntrackedFiles :: [Text] -> IO ()
+    removeUntrackedFiles = mapM_ $ \file -> void $ "git" $| ["reset", file]
diff --git a/src/Hit/Git/Status.hs b/src/Hit/Git/Status.hs
new file mode 100644
--- /dev/null
+++ b/src/Hit/Git/Status.hs
@@ -0,0 +1,177 @@
+{- | Data types that describe model of the @git diff@ command to display diffs
+in pretty way.
+-}
+
+module Hit.Git.Status
+       ( showPrettyDiff
+       ) where
+
+import Shellmet (($?), ($|))
+import System.Process (callCommand)
+
+import Hit.ColorTerminal (blueCode, boldCode, cyanCode, greenCode, magentaCode, redCode, resetCode,
+                          yellowCode)
+
+import qualified Data.Text as T
+
+
+-- | Enum that represents all possible types of file modifications.
+data PatchType
+    = Added
+    | Copied
+    | Deleted
+    | Modified
+    | Renamed
+    | TypeChanged
+    | Unmerged
+    | Unknown
+    | BrokenPairing
+
+-- | Map conventional characters to 'PatchType'
+parsePatchType :: Text -> Maybe PatchType
+parsePatchType = \case
+    "A" -> Just Added
+    "C" -> Just Copied
+    "D" -> Just Deleted
+    "M" -> Just Modified
+    "R" -> Just Renamed
+    "T" -> Just TypeChanged
+    "U" -> Just Unmerged
+    "X" -> Just Unknown
+    "B" -> Just BrokenPairing
+    _   -> Nothing
+
+-- | Display 'PatchType' in colorful and expanded text.
+displayPatchType :: PatchType -> Text
+displayPatchType = \case
+    Added         -> coloredIn greenCode   "added"
+    Copied        -> coloredIn blueCode    "copied"
+    Deleted       -> coloredIn redCode     "deleted"
+    Modified      -> coloredIn magentaCode "modified"
+    Renamed       -> coloredIn yellowCode  "renamed"
+    TypeChanged   -> coloredIn cyanCode    "type-changed"
+    Unmerged      -> inBold                "unmerged"
+    Unknown       -> inBold                "unknown"
+    BrokenPairing -> inBold                "broken"
+  where
+    coloredIn :: Text -> Text -> Text
+    coloredIn color text = color <> inBold text
+
+    inBold :: Text -> Text
+    inBold text = boldCode <> text <> resetCode
+
+-- | Output of the @git diff --name-status@ command.
+data DiffName = DiffName
+    { diffNameFile :: !Text       -- ^ file name
+    , diffNameType :: !PatchType  -- ^ type of the changed file
+    }
+
+parseDiffName :: [Text] -> Maybe DiffName
+parseDiffName [t, name] = DiffName name <$> parsePatchType t
+parseDiffName _         = Nothing
+
+-- | Output of the @git diff --stat@ command.
+data DiffStat = DiffStat
+    { diffStatFile  :: !Text  -- ^ file name
+    , diffStatCount :: !Text  -- ^ number of changed lines
+    , diffStatSigns :: !Text  -- ^ + and - stats
+    }
+
+{- | This command parses diff stats in the following format:
+
+@
+<filename> | <n> <pluses-and-minuses>
+@
+
+It also handles special case of binary files. Typical raw text returned by @git@
+can look like this:
+
+@
+ .foo.un~  | Bin 0 -> 523 bytes
+ README.md |   4 ++++
+ foo       |   1 +
+@
+-}
+parseDiffStat :: [Text] -> Maybe DiffStat
+parseDiffStat = \case
+    [diffStatFile, diffStatCount, diffStatSigns] -> Just DiffStat{..}
+    diffStatFile:"Bin":rest -> Just DiffStat
+        { diffStatCount = "Bin"
+        , diffStatSigns = unwords rest
+        , ..
+        }
+    _ -> Nothing
+
+showPrettyDiff :: Text -> IO ()
+showPrettyDiff commit = do
+    -- 1. Check rebase in progress and tell about it
+    whenM isRebaseInProgress $ do
+        putTextLn gitRebaseHelp
+        showConlictFiles
+
+    -- 2. Output pretty diff
+    diffName <- map words   . lines <$> "git" $| ["diff", commit, "--name-status"]
+    diffStat <- map toStats . lines <$> "git" $| ["diff", commit, "--stat", "--color=always"]
+    let fileTypes = sortWith diffNameFile $ mapMaybe parseDiffName diffName
+    let fileStats = sortWith diffStatFile $ mapMaybe parseDiffStat diffStat
+    let rows = zipWith joinDiffs fileTypes fileStats
+    putText $ formatTableAligned rows
+  where
+    toStats :: Text -> [Text]
+    toStats = foldMap words . T.split (== '|')
+
+    joinDiffs :: DiffName -> DiffStat -> (Text, Text, Text, Text)
+    joinDiffs DiffName{..} DiffStat{..} =
+        (displayPatchType diffNameType, diffNameFile, diffStatCount, diffStatSigns)
+
+    formatTableAligned :: [(Text, Text, Text, Text)] -> Text
+    formatTableAligned rows = unlines $ map formatRow rows
+      where
+        formatRow :: (Text, Text, Text, Text) -> Text
+        formatRow (fileType, fileName, fileCount, fileSigns) =
+            padRight typeSize fileType
+            <> "  "
+            <> padRight nameSize fileName
+            <> " | "
+            <> padLeft countSize fileCount
+            <> " "
+            <> fileSigns
+
+        padRight :: Int -> Text -> Text
+        padRight n t = t <> T.replicate (n - T.length t) " "
+
+        padLeft :: Int -> Text -> Text
+        padLeft n t = T.replicate (n - T.length t) " " <> t
+
+        typeSize, nameSize :: Int
+        typeSize  = maxOn (\(a, _, _, _) -> a) rows
+        nameSize  = maxOn (\(_, b, _, _) -> b) rows
+        countSize = maxOn (\(_, _, c, _) -> c) rows
+
+        maxOn :: (a -> Text) -> [a] -> Int
+        maxOn f = foldl' (\acc a -> max acc $ T.length $ f a) 0
+
+{- | Returns 'True' if rebase is in progress. Calls magic comand and if this
+command exits with code 1 then there's no rebase in progress.
+-}
+isRebaseInProgress :: IO Bool
+isRebaseInProgress = do
+    let checkRebaseCmd = callCommand "ls `git rev-parse --git-dir` | grep rebase > /dev/null 2>&1"
+    True <$ checkRebaseCmd $? pure False
+
+gitRebaseHelp :: Text
+gitRebaseHelp = unlines
+    [ ""
+    , boldCode <> yellowCode <> "Rebase in progress! What you can do:" <> resetCode
+    , "    " <> cyanCode <> "git rebase --continue " <> resetCode <> ": after fixing conflicts"
+    , "    " <> cyanCode <> "git rebase --skip     " <> resetCode <> ": to skip this patch"
+    , "    " <> cyanCode <> "git rebase --abort    " <> resetCode <> ": to abort to the original branch"
+    ]
+
+showConlictFiles :: IO ()
+showConlictFiles = do
+    conflictFiles <- lines <$> "git" $| ["diff", "--name-only", "--diff-filter=U"]
+    unless (null conflictFiles) $
+        putTextLn $ unlines $
+            ( boldCode <> redCode <> "Conflict files:" <> resetCode )
+            : map ("    " <>) conflictFiles
diff --git a/test/Main.hs b/test/Main.hs
new file mode 100644
--- /dev/null
+++ b/test/Main.hs
@@ -0,0 +1,32 @@
+
+module Main (main) where
+
+import GitHub.Data.Name (Name (..))
+import Test.Hspec (describe, hspec, it, shouldBe)
+
+import Hit.Issue (parseOwnerRepo)
+
+
+main :: IO ()
+main = hspec $ do
+    describe "parseOwnerRepo" $ do
+        let expectedOwnerName = N "kowainik"
+        let expectedRepoName = N "hit-on"
+        let expectedCredentials = Just (expectedOwnerName, expectedRepoName)
+        it "Parses a GitHub repo link (SSH) and gives use the Owner Name and Repo Name separately" $ do
+            parseOwnerRepo "git@github.com:kowainik/hit-on.git" `shouldBe` expectedCredentials
+        it "Parses a GitHub repo link (SSH) and gives use the Owner Name and Repo Name separately" $ do
+            parseOwnerRepo "git@github.com:kowainik/hit-on" `shouldBe` expectedCredentials
+        it "Parses a GitHub repo link (HTTPS) and gives use the Owner Name and Repo Name separately" $ do
+            parseOwnerRepo "https://github.com/kowainik/hit-on.git" `shouldBe` expectedCredentials
+        it "Parses a GitHub repo link (HTTPS) and gives use the Owner Name and Repo Name separately" $ do
+            parseOwnerRepo "https://github.com/kowainik/hit-on" `shouldBe` expectedCredentials
+        it "Parses an invalid GitHub repo link and returns a `Nothing`" $ do
+            parseOwnerRepo "github.com/kowainik/hit-on" `shouldBe` Nothing
+        it "Parses an invalid GitHub repo link and returns a `Nothing`" $ do
+            parseOwnerRepo "https://githu.com/kowainik/hit-on" `shouldBe` Nothing
+        it "Parses an invalid GitHub repo link and returns a `Nothing`" $ do
+            parseOwnerRepo "https://github.com/kowainik" `shouldBe` Nothing
+        it "Parses an invalid GitHub repo link and returns a `Nothing`" $ do
+            parseOwnerRepo "git@github.com" `shouldBe` Nothing
+
