diff --git a/bin/git-whitespace-hook b/bin/git-whitespace-hook
new file mode 100755
index 0000000000000000000000000000000000000000..adf649767082b08c39a81313616ebf38bc92d61f
--- /dev/null
+++ b/bin/git-whitespace-hook
@@ -0,0 +1,128 @@
+#!/bin/sh
+# dune-git-whitespace-hook
+# DO NOT TOUCH THE PRECEDING LINE
+# It is used by dunecontrol to enable automatic updates of the whitespace hook
+
+# DUNE pre-commit hook to enforce whitespace policy
+# This hook prevents adding lines with trailing whitespace and or tab characters
+# in line indentation for certain files (see the TRAILING_WHITESPACE_DEFAULT and
+# TAB_IN_INDENT_DEFAULT variables below for the default sets of files that will
+# be checked).
+# You can tell the hook which files should be inspected by setting the Git
+# configuration variables "hooks.whitespace.trailing" and "hooks.whitespace.tabinindent".
+# Those variables should contain valid Perl regular expressions. The names of modified
+# files will be matched against those regexes.
+
+# git-diff-index needs a valid commit to compare to
+if git-rev-parse --verify HEAD 2>/dev/null
+then
+	against=HEAD
+else
+	# Initial commit: diff against an empty tree object
+	against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
+fi
+
+
+# By default, we disallow trailing whitespace for the following files, but the check for C/C++ sources
+# happens in the tab-in-indent check to avoid confusing users with duplicate error messages
+TRAILING_WHITESPACE_DEFAULT='.*(Makefile.am|configure.ac|dune.module|README|README.SVN|COPYING|INSTALL|TODO|\.cmake|CMakeLists.txt|\.pc\.in)$'
+
+# By default, we disallow tabs in indents and trailing whitespace in C/C++ source files
+TAB_IN_INDENT_DEFAULT='\.(cpp|hpp|cc|hh|c|h)$'
+
+# Get user preferences
+TRAILING_WHITESPACE_FILES=$(git config hooks.whitespace.trailing)
+
+# Set default regex for disallowing trailing whitespace if the user did not set anything.
+# We need to check the return value of git-config to distinguish the case
+# when the user set an empty value
+if [ $? -ne 0 ];
+then
+  TRAILING_WHITESPACE_FILES="$TRAILING_WHITESPACE_DEFAULT"
+fi
+
+
+TAB_IN_INDENT_FILES=$(git config hooks.whitespace.tabinindent)
+
+# Set default regex for disallowing tabs if the user did not set anything.
+# We need to check the return value of git-config to distinguish the case
+# when the user set an empty value
+if [ $? -ne 0 ];
+then
+  TAB_IN_INDENT_FILES="$TAB_IN_INDENT_DEFAULT"
+fi
+
+
+# Unfortunately, we have to mess directly with the repository config file,
+# as git won't honor a custom config file specified by GIT_CONFIG
+
+# backup repository-local user setting for core.whitespace
+USER_WHITESPACE=$(git config --local --get core.whitespace)
+if [ $? -ne 0 ];
+then
+  USER_HAS_CUSTOM_WHITESPACE=0
+else
+  USER_HAS_CUSTOM_WHITESPACE=1
+fi
+
+fail=0
+done=0
+
+restore_config()
+{
+  if [ $done -ne 1 ];
+  then
+    echo "Error while executing whitespace checking pre-commit hook!" 1>&2
+    echo "There might still be whitespace errors in your commit!" 1>&2
+  fi
+
+  if [ $USER_HAS_CUSTOM_WHITESPACE -eq 1 ];
+  then
+    git config --replace-all core.whitespace "$USER_WHITESPACE"
+  else
+    git config --unset core.whitespace
+  fi
+
+  # be nice and let the commit go through if something went wrong along the
+  # way and we did not record a failure
+  exit $fail
+}
+
+trap restore_config EXIT
+
+# set custom value
+git config --replace-all core.whitespace trailing-space
+
+if [ -z "$TRAILING_WHITESPACE_FILES" ];
+then
+  git diff-index --check --cached $against --
+  result=$?
+else
+  git diff-index --cached --name-only $against | perl -ne "print if /$TRAILING_WHITESPACE_FILES/" | xargs git diff-index --check --cached $against --
+  result=$?
+fi
+
+if [ $result -ne 0 ];
+then
+  fail=1
+fi
+
+git config --replace-all core.whitespace trailing-space,tab-in-indent
+
+if [ -z "$TAB_IN_INDENT_FILES" ];
+then
+  git diff-index --check --cached $against --
+  result=$?
+else
+  git diff-index --cached --name-only $against | perl -ne "print if /$TAB_IN_INDENT_FILES/" | xargs git diff-index --check --cached $against --
+  result=$?
+fi
+
+if [ $result -ne 0 ];
+then
+  fail=1
+fi
+
+done=1
+
+# trap will call the cleanup code