diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000000..554a06e7c1
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,31 @@
+
+# Custom attribute to mark source files using KiCad C++ formatting
+[attr]kicad-cpp-source whitepace=tab-in-indent format.clang-format-kicad
+
+# Custom attribute to mark KiCad's own CMake files
+[attr]kicad-cmake-source whitespace=tab-in-indent
+
+# Custom attribute for auto-generated sources:
+# * Do not perform whitespace checking
+# * Do not format
+[attr]generated whitespace=-tab-in-indent,-indent-with-non-tab -format.clang-format-kicad
+
+# By default, all C and C++ files conform to KiCad formatting,
+# unless overridden
+*.c         kicad-cpp-source
+*.cpp       kicad-cpp-source
+*.h         kicad-cpp-source
+
+*.cmake     kicad-cmake-source
+*.txt       kicad-cmake-source
+
+# Compiled bitmap sources
+bitmaps_png/cpp_*/*.cpp     generated
+
+# wxFormBuilder-generated files
+**/dialog*/*_base.cpp       generated
+**/dialog*/*_base.h         generated
+
+# Lemon grammars
+common/libeval/grammar.c    generated
+common/libeval/grammar.h    generated
diff --git a/.githooks/pre-commit.d/50-check-format b/.githooks/pre-commit.d/50-check-format
index 8de58b51e6..5995aa6ea4 100755
--- a/.githooks/pre-commit.d/50-check-format
+++ b/.githooks/pre-commit.d/50-check-format
@@ -30,20 +30,48 @@ check_git_config() {
     fi
 }
 
+get_filtered_filenames()
+{
+    format_attr='clang-format-kicad'
+
+    # command to get list of candidate files
+    git_list_files='git diff --cached --name-only --diff-filter=ACM'
+
+    files=$(${git_list_files} |
+
+        # Filter for format-controlled files
+        git check-attr --stdin format.${format_attr} |
+
+        # output only the file names
+        grep ": set$" |
+        cut -d: -f1)
+
+    echo ${files}
+}
+
 check_clang_format
 check_git_config
 
-readonly out=$(git clang-format -v --diff)
+files_to_check=$(get_filtered_filenames)
+
+if [ -z "${files_to_check}" ]; then
+    # No controlled files to check
+    exit 0;
+fi
+
+git_clang_format_cmd="git clang-format -v --diff -- ${files_to_check}"
+
+readonly out=$(${git_clang_format_cmd})
 
 # In these cases, there is no formatting issues, so we succeed
 if [[ "$out" == *"no modified files to format"* ]]; then exit 0; fi
 if [[ "$out" == *"clang-format did not modify any files"* ]]; then exit 0; fi
 
 # Any other case implies formatting results
-echo "ERROR: you need to run git clang-format on your commit"
+echo "ERROR: you need to run clang-format (e.g. using tools/check_coding.sh) on your commit"
 
 # print the errors to show what's the issue
-git clang-format -v --diff
+${git_clang_format_cmd}
 
 # fail the pre-commit
 exit 1
diff --git a/Documentation/development/coding-style-policy.md b/Documentation/development/coding-style-policy.md
index b4e2abe8c6..a4da373637 100644
--- a/Documentation/development/coding-style-policy.md
+++ b/Documentation/development/coding-style-policy.md
@@ -72,18 +72,25 @@ Set the `git clang-format` tool to use the provided `_clang-format` file:
 
 Then, to enable the format checker, set the `KICAD_CHECK_FORMAT` environment
 variable in your shell. Without this variable, the format checker will not
-run on commit, but you can still use `git clang-format --diff` to check manually.
+run on commit, but you can still check files staged for commit manually:
 
-If enabled, when you commit a change, you will be told if you have caused any
-style violations (only in your changed code). You can fix them automatically
-with:
+    tools/check_coding.sh --diff
 
-    git clang-format
+If the hook is enabled, when you commit a change, you will be told if you
+have caused any style violations (only in your changed code). You can fix your
+staged changes automatically with this tool:
+
+    tools/check_coding.sh
 
 Or you can proceed anyway, if you are sure your style is correct:
 
     git commit --no-verify
 
+The `check_coding.sh` tool has other modes:
+
+* Make (or see only) changes to files modified in the previous commit:
+    * `check_coding.sh --amend [--diff]`
+
 
 # 2. Naming Conventions # {#naming_conventions}
 Before delving into anything as esoteric as indentation and formatting,
diff --git a/tools/check_coding.sh b/tools/check_coding.sh
new file mode 100755
index 0000000000..c5f730dfbc
--- /dev/null
+++ b/tools/check_coding.sh
@@ -0,0 +1,107 @@
+#!/usr/bin/env bash
+
+#  This program source code file is part of KICAD, a free EDA CAD application.
+#
+#  Copyright (C) 2019 Kicad Developers, see AUTHORS.txt for contributors.
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, you may find one here:
+#  http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+#  or you may search the http://www.gnu.org website for the version 2 license,
+#  or you may write to the Free Software Foundation, Inc.,
+#  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+
+# Simple program to check and fix formatting in KiCad source files,
+# while ignoring violations in "uncontrolled" files, such as generated files
+# or 3rd party sources.
+
+usage='usage: check_coding.sh [<options>] [--]
+     --help                     Print usage plus more detailed help.
+
+     --diff                     Only show proposed changes, do not format files
+
+     --cached                   Re-format changes currently staged for commit
+     --amend                    Re-format changes made in the previous commit
+'
+
+help="$usage"'
+Example to format cached files:
+    check_coding.sh
+
+To show what would be done:
+    check_coding.sh --diff
+'
+
+die() {
+    echo "$@" 1>&2; exit 1
+}
+
+# Parse command-line arguments.
+diff=false
+mode='cached'
+
+while test "$#" != 0; do
+    case "$1" in
+    --diff) diff=true ;;
+    --amend) mode='amend' ;;
+    --cached) mode='cached' ;;
+    --) shift ; break ;;
+    -*) die "$usage" ;;
+    *) break ;;
+    esac
+    shift
+done
+
+test "$#" = 0 || die "$usage"
+
+# This is the main KiCad formatting attribute
+# used by .gitattributes to mark KiCad source files
+format_attribute="format.clang-format-kicad"
+
+format_commit='HEAD'
+
+# Select the git file list command and the commit to check
+case "${mode}" in
+    '')       echo "$usage"; exit 0 ;;
+    amend)
+        # Files changed by the last commit
+        git_list_files='git diff-tree  --diff-filter=ACM --name-only HEAD -r --no-commit-id'
+        format_commit='HEAD^'
+        ;;
+    cached)
+        # Currently staged files
+        git_list_files='git diff-index --diff-filter=ACM --name-only HEAD --cached'
+        ;;
+    *) die "Invalid mode: $mode" ;;
+esac
+
+
+if [ "${diff}" = true ]; then
+    # Only show the proposed changes
+    format_command="git clang-format --diff ${format_commit}"
+else
+    # Actually make the changes
+    format_command="git clang-format ${format_commit}"
+fi
+
+${git_list_files} |
+
+    # Filter sources with the formatting attribute set
+    git check-attr ${format_attribute} --stdin |
+
+    # output only the file names
+    grep ": set$" |
+    cut -d: -f1 |
+
+    # Apply the formatting command
+    xargs -d '\n' ${format_command}