diff --git a/CMakeLists.txt b/CMakeLists.txt
index 66de4f3b1b207c575ace1e5c385edd15ee95a3e1..97798570027adcb01b75d2d732a559f0efdf90d3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -29,21 +29,10 @@ project (Pastis)
 list(APPEND CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} -O3)
 
 add_subdirectory(${CMAKE_SOURCE_DIR}/packages/kokkos)
-include_directories(${Kokkos_INCLUDE_DIRS_RET})
-
-list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake-modules")
-include(GetGitRevisionDescription)
-
-get_git_head_revision(GITREV GITHASH)
-git_local_changes(GITHASLOCALCHANGES)
+add_subdirectory(utils)
 
-add_custom_target(git_revision ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/git_revision.hpp)
-set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/git_revision.hpp PROPERTIES GENERATED TRUE HEADER_FILE_ONLY TRUE)
-
-configure_file("${CMAKE_CURRENT_SOURCE_DIR}/git_revision.hpp.in" "${CMAKE_CURRENT_BINARY_DIR}/git_revision.hpp" @ONLY)
-
-list(APPEND SOURCES git_revision.hpp)
-include_directories(${CMAKE_BINARY_DIR})
+include_directories(${Kokkos_INCLUDE_DIRS_RET})
+include_directories(utils)
 
 add_executable(pastis main.cpp)
-target_link_libraries(pastis kokkos)
+target_link_libraries(pastis kokkos PastisUtils)
diff --git a/git_revision.hpp.in b/git_revision.hpp.in
deleted file mode 100644
index 86b65c4adc3f26a4ff2ffca8ab8f82e8268f37cb..0000000000000000000000000000000000000000
--- a/git_revision.hpp.in
+++ /dev/null
@@ -1,3 +0,0 @@
-#define GITREV "@GITREV@"
-#define GITHASH "@GITHASH@"
-#define GITHASLOCALCHANGES "@GITHASLOCALCHANGES@"
diff --git a/main.cpp b/main.cpp
index 4675d52d50de8e50d151c244c1efb9bb86d49b22..affb12fd5554578b2ef4eddb45009bdaa497642f 100644
--- a/main.cpp
+++ b/main.cpp
@@ -1,13 +1,15 @@
 #include <iostream>
 #include <Kokkos_Core.hpp>
-#include <git_revision.hpp>
+#include <RevisionInfo.hpp>
 
 int main(int argc, char *argv[])
 {
   std::cout << "It's pastis time!\n";
+
   std::cout << "--------------------- git info --------------------------\n";
-  std::cout << "* branch: " << GITREV << '\n';
-  std::cout << "*   hash: " << GITHASH << '(' << GITHASLOCALCHANGES << ")\n";
+  std::cout << "* version: " << RevisionInfo::version() << '\n';
+  std::cout << "* head: " << RevisionInfo::head() << '\n';
+  std::cout << "* hash: " << RevisionInfo::hash() << "  (" << RevisionInfo::isClean() << ")\n";
   std::cout << "---------------------------------------------------------\n";
 
   Kokkos::initialize(argc, argv);
diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e08c25820a511ec82ceefe278c068674ff9343a1
--- /dev/null
+++ b/utils/CMakeLists.txt
@@ -0,0 +1,19 @@
+include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
+
+list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/cmake-modules")
+include(GetGitRevisionDescription)
+
+git_describe(PASTISVERSION "--abbrev=0")
+get_git_head_revision(PASTISHEAD PASTISHASH)
+git_local_changes(PASTISHASLOCALCHANGES)
+
+add_custom_target(git_revision ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/pastis_git_revision.hpp)
+set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/pastis_git_revision.hpp PROPERTIES GENERATED TRUE HEADER_FILE_ONLY TRUE)
+
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/pastis_git_revision.hpp.in" "${CMAKE_CURRENT_BINARY_DIR}/pastis_git_revision.hpp" @ONLY)
+
+list(APPEND SOURCES pastis_git_revision.hpp)
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
+
+add_library(PastisUtils RevisionInfo.cpp)
diff --git a/utils/RevisionInfo.cpp b/utils/RevisionInfo.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..712aa5152ffb072ac291456b006240c5e564207c
--- /dev/null
+++ b/utils/RevisionInfo.cpp
@@ -0,0 +1,22 @@
+#include <RevisionInfo.hpp>
+#include <pastis_git_revision.hpp>
+
+std::string RevisionInfo::version()
+{
+  return PASTISVERSION;
+}
+
+std::string RevisionInfo::head()
+{
+  return PASTISHEAD;
+}
+
+std::string RevisionInfo::hash()
+{
+  return PASTISHASH;
+}
+
+std::string RevisionInfo::isClean()
+{
+  return PASTISHASLOCALCHANGES;
+}
diff --git a/utils/RevisionInfo.hpp b/utils/RevisionInfo.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..57219226b6fff90ca11e590f25f0816788bb56ea
--- /dev/null
+++ b/utils/RevisionInfo.hpp
@@ -0,0 +1,14 @@
+#ifndef REVISION_INFO_HPP
+#define REVISION_INFO_HPP
+
+#include <string>
+
+struct RevisionInfo
+{
+  static std::string version();
+  static std::string head();
+  static std::string hash();
+  static std::string isClean();
+};
+
+#endif // REVISION_INFO_HPP
diff --git a/utils/pastis_git_revision.hpp.in b/utils/pastis_git_revision.hpp.in
new file mode 100644
index 0000000000000000000000000000000000000000..0398abebe6b4d43ba155e5e7ad47c4dcc2443e0b
--- /dev/null
+++ b/utils/pastis_git_revision.hpp.in
@@ -0,0 +1,9 @@
+#ifndef GIT_REVISION_HPP
+#define GIT_REVISION_HPP
+
+#define PASTISVERSION "@PASTISVERSION@"
+#define PASTISHEAD "@PASTISHEAD@"
+#define PASTISHASH "@PASTISHASH@"
+#define PASTISHASLOCALCHANGES "@PASTISHASLOCALCHANGES@"
+
+#endif // GIT_REVISION_HPP