diff --git a/apply.c b/apply.c
index a65a354eef5..2de8bb203d7 100644
--- a/apply.c
+++ b/apply.c
@@ -32,6 +32,7 @@
 #include "entry.h"
 #include "setup.h"
 #include "symlinks.h"
+#include "ws.h"
 #include "wrapper.h"
 
 struct gitdiff_data {
diff --git a/cache.h b/cache.h
index 0570f9ad07d..dde275c9301 100644
--- a/cache.h
+++ b/cache.h
@@ -603,32 +603,6 @@ int add_files_to_cache(const char *prefix, const struct pathspec *pathspec, int
 /* diff.c */
 extern int diff_auto_refresh_index;
 
-/*
- * whitespace rules.
- * used by both diff and apply
- * last two digits are tab width
- */
-#define WS_BLANK_AT_EOL         0100
-#define WS_SPACE_BEFORE_TAB     0200
-#define WS_INDENT_WITH_NON_TAB  0400
-#define WS_CR_AT_EOL           01000
-#define WS_BLANK_AT_EOF        02000
-#define WS_TAB_IN_INDENT       04000
-#define WS_TRAILING_SPACE      (WS_BLANK_AT_EOL|WS_BLANK_AT_EOF)
-#define WS_DEFAULT_RULE (WS_TRAILING_SPACE|WS_SPACE_BEFORE_TAB|8)
-#define WS_TAB_WIDTH_MASK        077
-/* All WS_* -- when extended, adapt diff.c emit_symbol */
-#define WS_RULE_MASK           07777
-extern unsigned whitespace_rule_cfg;
-unsigned whitespace_rule(struct index_state *, const char *);
-unsigned parse_whitespace_rule(const char *);
-unsigned ws_check(const char *line, int len, unsigned ws_rule);
-void ws_check_emit(const char *line, int len, unsigned ws_rule, FILE *stream, const char *set, const char *reset, const char *ws);
-char *whitespace_error_string(unsigned ws);
-void ws_fix_copy(struct strbuf *, const char *, int, unsigned, int *);
-int ws_blank_line(const char *line, int len);
-#define ws_tab_width(rule)     ((rule) & WS_TAB_WIDTH_MASK)
-
 /* ls-files */
 void overlay_tree_on_index(struct index_state *istate,
 			   const char *tree_name, const char *prefix);
diff --git a/config.c b/config.c
index 9beba19b41c..97063a0743e 100644
--- a/config.c
+++ b/config.c
@@ -35,6 +35,7 @@
 #include "setup.h"
 #include "trace2.h"
 #include "worktree.h"
+#include "ws.h"
 #include "wrapper.h"
 #include "write-or-die.h"
 
diff --git a/diff.c b/diff.c
index e697f78a645..73d2ac03673 100644
--- a/diff.c
+++ b/diff.c
@@ -41,6 +41,7 @@
 #include "object-name.h"
 #include "setup.h"
 #include "strmap.h"
+#include "ws.h"
 #include "wrapper.h"
 
 #ifdef NO_FAST_WORKING_DIRECTORY
diff --git a/environment.c b/environment.c
index 8a96997539a..541f0b19acf 100644
--- a/environment.c
+++ b/environment.c
@@ -67,7 +67,6 @@ int read_replace_refs = 1;
 enum eol core_eol = EOL_UNSET;
 int global_conv_flags_eol = CONV_EOL_RNDTRP_WARN;
 char *check_roundtrip_encoding = "SHIFT-JIS";
-unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;
 enum branch_track git_branch_track = BRANCH_TRACK_REMOTE;
 enum rebase_setup_type autorebase = AUTOREBASE_NEVER;
 enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;
diff --git a/ws.c b/ws.c
index 036ccb8ee9d..d356d4ec9ee 100644
--- a/ws.c
+++ b/ws.c
@@ -3,9 +3,12 @@
  *
  * Copyright (c) 2007 Junio C Hamano
  */
-#include "cache.h"
+#include "git-compat-util.h"
 #include "attr.h"
 #include "strbuf.h"
+#include "ws.h"
+
+unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;
 
 static struct whitespace_rule {
 	const char *rule_name;
diff --git a/ws.h b/ws.h
new file mode 100644
index 00000000000..5ba676c5595
--- /dev/null
+++ b/ws.h
@@ -0,0 +1,33 @@
+#ifndef WS_H
+#define WS_H
+
+struct index_state;
+struct strbuf;
+
+/*
+ * whitespace rules.
+ * used by both diff and apply
+ * last two digits are tab width
+ */
+#define WS_BLANK_AT_EOL         0100
+#define WS_SPACE_BEFORE_TAB     0200
+#define WS_INDENT_WITH_NON_TAB  0400
+#define WS_CR_AT_EOL           01000
+#define WS_BLANK_AT_EOF        02000
+#define WS_TAB_IN_INDENT       04000
+#define WS_TRAILING_SPACE      (WS_BLANK_AT_EOL|WS_BLANK_AT_EOF)
+#define WS_DEFAULT_RULE (WS_TRAILING_SPACE|WS_SPACE_BEFORE_TAB|8)
+#define WS_TAB_WIDTH_MASK        077
+/* All WS_* -- when extended, adapt diff.c emit_symbol */
+#define WS_RULE_MASK           07777
+extern unsigned whitespace_rule_cfg;
+unsigned whitespace_rule(struct index_state *, const char *);
+unsigned parse_whitespace_rule(const char *);
+unsigned ws_check(const char *line, int len, unsigned ws_rule);
+void ws_check_emit(const char *line, int len, unsigned ws_rule, FILE *stream, const char *set, const char *reset, const char *ws);
+char *whitespace_error_string(unsigned ws);
+void ws_fix_copy(struct strbuf *, const char *, int, unsigned, int *);
+int ws_blank_line(const char *line, int len);
+#define ws_tab_width(rule)     ((rule) & WS_TAB_WIDTH_MASK)
+
+#endif /* WS_H */
