diff --git a/bin/hooks/git_hook_main b/bin/hooks/git_hook_main
index 37657af03c9d402dfeb85dc2d1b2afd303663e8f..556adc5c8f74ca4c90d628767e75ae6977f83c64 100755
--- a/bin/hooks/git_hook_main
+++ b/bin/hooks/git_hook_main
@@ -15,7 +15,7 @@ import re
 from aslint.i18n import _
 from aslint.logger import SetLevelAction, logger
 from aslint.utils import remove_lines
-from hgaster.hooks.codeaster import precommit_git
+from hgaster.hooks.codeaster import precommit_git, run_ctest_minimal
 from hgaster.hooks.generic import NOOK, OK, check_commit_msg
 from repository_api import repository_switch
 
@@ -37,6 +37,9 @@ def main(repotype, repopath, hook, amend, *args):
             logger.error("commit-msg: check commit message ended with errors.")
         return OK
 
+    if hook == "pre-push":
+        return run_ctest_minimal(repopath)
+
     logger.error(_("hook '{0}' is not defined").format(hook))
     return 1
 
@@ -62,16 +65,14 @@ if __name__ == "__main__":
         help=_("call commit-msg hook"),
     )
     parser.add_argument(
-        "--amend",
-        action="store_true",
-        help=_("enabled for 'commit --amend'"),
-    )
-    parser.add_argument(
-        "-R",
-        "--repository",
-        default=".",
-        help=_("repository path"),
+        "--pre-push",
+        action="store_const",
+        dest="hook",
+        const="pre-push",
+        help=_("call pre-push hook"),
     )
+    parser.add_argument("--amend", action="store_true", help=_("enabled for 'commit --amend'"))
+    parser.add_argument("-R", "--repository", default=".", help=_("repository path"))
     parser.add_argument("paths", nargs="*", help="additional arguments passed to hook script")
 
     args = parser.parse_args()
diff --git a/bin/install_env b/bin/install_env
index 0d1599e077093aa688159abd88d459f9ae395642..e37c2b49e4f379b5bcdc9816565d1a5a0e1cd24c 100755
--- a/bin/install_env
+++ b/bin/install_env
@@ -274,7 +274,7 @@ def main(repocfg, repodir, options):
                     git_config_set("remote.origin.url", asked)
 
             entrypoint = osp.join(InstallEnv.root, "bin", "hooks", "git_hook_entrypoint")
-            for hook in ("commit-msg", "pre-commit"):
+            for hook in ("commit-msg", "pre-commit", "pre-push"):
                 dest = osp.join(osp.join(rootdir, repo), ".git", "hooks", hook)
                 if options.reset and (osp.exists(dest) or osp.lexists(dest)):
                     os.remove(dest)
diff --git a/lib/aslint/config.py b/lib/aslint/config.py
index da7aca6dbdd84aba27acf7bd9745fb6c4e72b24a..81d2c641a08545bf94b8c846112a3b197a30fe45 100644
--- a/lib/aslint/config.py
+++ b/lib/aslint/config.py
@@ -95,6 +95,7 @@ class AsterCfgSection(object):  # pragma pylint: disable=R0902
         "check_commit",
         "check_submit",
         "check_precommit",
+        "check_prepush",
         "docaster_uri",
         "docaster_cafile",
         "clang_format",
@@ -132,6 +133,7 @@ class AsterCfgSection(object):  # pragma pylint: disable=R0902
         self.check_commit = _read("check-commit", "warn")
         self.check_submit = _read("check-submit", "warn")
         self.check_precommit = _read("check-precommit", "undef")
+        self.check_prepush = _read("check-prepush", "undef")
         # installation root of devtools
         self.aslint_root = get_absolute_dirname(__file__)
         self.devtools_root = get_absolute_dirname(osp.join(self.aslint_root, os.pardir))
diff --git a/lib/hgaster/hooks/codeaster.py b/lib/hgaster/hooks/codeaster.py
index 443b900e591ebb7d82e28ac1e31eb749e2009751..98203e1cde38513762f0a0171a708fd99665ab09 100644
--- a/lib/hgaster/hooks/codeaster.py
+++ b/lib/hgaster/hooks/codeaster.py
@@ -4,18 +4,13 @@
 
 import os
 import os.path as osp
+from pathlib import Path
 
 from aslint.logger import logger
 from repository_api import get_branch, get_main_branch, get_repo_name, repository_type
 
 from ..ext_utils import get_changed_files, is_admin
-from .generic import (
-    NOOK,
-    OK,
-    branch_checker,
-    branch_user_commit_hook,
-    branch_user_push_hook,
-)
+from .generic import NOOK, OK, branch_checker, branch_user_commit_hook, branch_user_push_hook
 
 # authorized branches names (+ vNN)
 AUTH_BRANCH = ("^default$", "^edf/", "^asterxx/", "^v([0-9]+(\.[0-9]+)?(_smeca)?)$")
@@ -37,10 +32,7 @@ def precommit_git(repopath, amend):
     # do pretxncommit: check branch, message
     branch = get_branch(repopath)
     if git_branch_checker(branch) is NOOK:
-        logger.error(
-            "You are not allowed to commit in " "branch {0!r}.".format(branch),
-            exit=True,
-        )
+        logger.error("You are not allowed to commit in " "branch {0!r}.".format(branch), exit=True)
     return aslint(repopath, amend=amend)
 
 
@@ -62,29 +54,9 @@ def aslint(repopath, paths=(), amend=False):
     revs = ("HEAD~1",) if amend else None
 
     # logger.title("running aslint...")
-    choice = ASCFG.get("check.precommit")
-    if choice == "no":
-        logger.warn(
-            "pre-commit checkings skipped because of 'check-precommit'"
-            " value in your ~/.gitconfig file"
-        )
+    if _check_preference("pre-commit") == OK:
         return OK
-    elif choice == "undef":
-        logger.info(
-            "pre-commit: If you don't plan to submit your work "
-            "you can disable these checkings by adding "
-            "'check-precommit = no' in the [aster] section in "
-            "your ~/.gitconfig file."
-        )
-        logger.info(
-            "pre-commit: To hide this message you can set the value "
-            "'check-precommit = yes'."
-        )
-    elif choice != "yes":
-        logger.warn(
-            "unknown choice {0!r} for 'check.precommit'"
-            " (see ~/.gitconfig) must be 'yes' or 'no'.".format(choice)
-        )
+
     dchg = get_changed_files(repopath, revs=revs, files=paths)
     changes = filter_dict(dchg)
     report = Report()
@@ -115,9 +87,7 @@ def aslint(repopath, paths=(), amend=False):
         else:
             logger.info("pre-commit: no files to be checked")
         if fixed and repository_type(repopath) == "git":
-            logger.warn(
-                "pre-commit: some files were automatically fixed and added by running:"
-            )
+            logger.warn("pre-commit: some files were automatically fixed and added by running:")
             toadd = dchg.get("A", []) + dchg.get("M", [])
             cmd = ["git", "add"] + toadd
             logger.info(" ".join(cmd))
@@ -127,7 +97,7 @@ def aslint(repopath, paths=(), amend=False):
         report.report_summary()
         answ = input(
             "The commit will be not accepted because of remaining "
-            "errors.\nDo you want to continue (y/n) ?"
+            "errors.\nDo you want to continue (y/n) ? "
         )
         if answ.lower() not in ("y", "o"):
             logger.info("pre-commit: aslint ended with errors.")
@@ -135,3 +105,83 @@ def aslint(repopath, paths=(), amend=False):
         else:
             logger.cancel_error()
     return OK
+
+
+def run_ctest_minimal(repopath):
+    """Run a minimal list of testcases.
+
+    Arguments:
+        repopath (str): Repository path.
+    """
+    from subprocess import call
+
+    from aslint.base_checkers import checkcontext
+    from aslint.check_files import read_waf_parameters
+    from aslint.config import ASCFG
+
+    checkcontext.reponame = get_repo_name(repopath)
+    if checkcontext.reponame != "src":
+        return OK
+    if _check_preference("pre-push") == OK:
+        return OK
+
+    logger.warning("Run a minimal list of testcases (for about 30 seconds).")
+
+    builddir = ASCFG.get("waf.builddir")
+    target = "release"
+    if os.environ.get("BUILD") == "debug":
+        builddir = "build/mpidebug" if osp.isdir("build/mpidebug") else "build/mpi"
+        target = "debug"
+    wafc4che = osp.join(builddir, "c4che", target + "_cache.py")
+    c4che = read_waf_parameters(wafc4che)
+    run_ctest = Path(c4che["BINDIR"]) / "run_ctest"
+
+    logger.info("NB: This version will be used: %s", run_ctest)
+    try:
+        answ = input("Do you want to continue (y/[n], 'Ctrl+C' to abort push) ? ")
+    except KeyboardInterrupt:
+        return NOOK
+    if answ.lower() not in ("y", "o"):
+        logger.info("run_ctest skipped.")
+        return OK
+
+    cmd = [run_ctest, "-R", "(asrun0|mumps02b|supv002|vocab0|zzzz509j)", "--no-resutest"]
+    if call(cmd):
+        return NOOK
+    return OK
+
+
+def _check_preference(hook):
+    """Check if a checking is enabled or disabled in '~/.gitconfig'.
+
+    Arguments:
+        hook (str): Hook name.
+
+    Returns:
+        bool: OK if the hook should be skipped, NOOK otherwise.
+    """
+    from aslint.config import ASCFG
+
+    assert hook in ("pre-commit", "pre-push"), hook
+    option = f"check.{hook.replace('-', '')}"
+    gitopt = option.replace(".", "-")
+
+    choice = ASCFG.get(option)
+    if choice == "no":
+        logger.warn(
+            "%s checkings skipped because of '%s'" " value in your ~/.gitconfig file", hook, gitopt
+        )
+        return OK
+    elif choice in (None, "undef"):
+        logger.info(
+            "%s: If you want to disable these checkings, just add "
+            "'%s = no' in the [aster] section in your ~/.gitconfig file.",
+            hook,
+            gitopt,
+        )
+        logger.info("%s: To hide this message you can set the value '%s = yes'.", hook, gitopt)
+    elif choice != "yes":
+        logger.warn(
+            "unknown choice %r for '%s' (see ~/.gitconfig) must be 'yes' or 'no'.", choice, option
+        )
+    return NOOK
diff --git a/lib/hgaster/hooks/generic.py b/lib/hgaster/hooks/generic.py
index 96f7feb30c0b44863c50a7d3eb1a060bbe87d772..99397b2f9643c1fd741204b55a4ac00dd993521d 100644
--- a/lib/hgaster/hooks/generic.py
+++ b/lib/hgaster/hooks/generic.py
@@ -14,7 +14,7 @@ from aslint.config import ASCFG
 from aslint.baseutils import force_list
 from aslint.logger import logger
 
-from ..ext_utils import RE_ISSUE, get_issues_from_descr, is_admin
+from ..ext_utils import RE_ISSUE, get_issues_from_descr
 
 OK, NOOK = 0, 1