├── LICENSE └── update.keep-first-parent-history.sh /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Lokku 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /update.keep-first-parent-history.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This update hook's purpose is to make sure that commits don't disappear from 4 | # "git log --first-parent master" server-side. This often happens when people 5 | # run "git pull" without --rebase. 6 | 7 | # Please don't modify this file outside of version control 8 | 9 | # TODO: make it work with empty repo 10 | 11 | 12 | refname="$1" 13 | oldrev="$2" 14 | newrev="$3" 15 | 16 | # --- Safety check 17 | if [ -z "$GIT_DIR" ]; then 18 | echo "Don't run this script from the command line." >&2 19 | echo " (if you want, you could supply GIT_DIR then run" >&2 20 | echo " $0 )" >&2 21 | exit 1 22 | fi 23 | 24 | if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then 25 | echo "Usage: $0 " >&2 26 | exit 1 27 | fi 28 | 29 | # We only want to enforce this hook on master: 30 | if [ "$refname" != "refs/heads/master" ] ; then 31 | exit 0 32 | fi 33 | 34 | # Just in case: 35 | if [ "$oldrev" = "$newrev" ] ; then 36 | exit 0 37 | fi 38 | 39 | # Now we want to check if $oldrev has disappeared from 'git log --first-parent 40 | # "$newrev"' by running: 41 | # 42 | # git rev-list --first-parent "$newrev" | grep -q "^$oldrev$" 43 | # 44 | # This is slow, because git rev-list prints out a large number of commits 45 | # SHA1s. Running this command should be equivalent, but optimized: 46 | # 47 | # git rev-list --first-parent "$oldrev^..$newrev" | grep -q "^$oldrev$" 48 | # 49 | # Note the ^ in the rev-list command. 50 | 51 | if git rev-list --first-parent "$oldrev"^.."$newrev" | grep -q "^$oldrev$" ; then 52 | true 53 | else 54 | echo "Error: this push hides some commits previously displayed in \"git log --first-parent $refname\" on the server's side" >&2 55 | echo "" >&2 56 | branchname="$(printf %s "$refname" | sed 's!^refs/heads/!!')" 57 | echo "This probably happened because you ran "git pull" without the --rebase flag (or because you ran "git push -f" after deleting previously published commits)." >&2 58 | echo "To fix the first problem, run these two commands client-side before pushing, replacing \"origin\" with the appropriate remote name:" >&2 59 | echo " # Update refs/remotes/origin/$branchname on the local machine to match the server's value" >&2 60 | echo " git fetch origin +refs/heads/$branchname:refs/remotes/origin/$branchname" >&2 61 | echo " # Rebase unpublished commits on published history:" >&2 62 | echo " git rebase origin/$branchname" >&2 63 | echo "This will linearize the unpublished history, there are other solutions if you want to keep merge commits." >&2 64 | echo "Check the result with \"git log --graph\" before pushing again." >&2 65 | exit 1 66 | fi 67 | 68 | # Do not allow "Merge branch 'master'" commit messages either in the --first-parent history. 69 | # 70 | # Hopefully, the vast majority of these case would have been caught by the earlier check. 71 | 72 | if git log --first-parent --format=%s "$oldrev".."$newrev" | grep -q "^Merge branch 'master'" ; then 73 | echo "Error: this push includes some commits in master's --first-parent history with the commit message \"Merge branch 'master'\"" >&2 74 | exit 1 75 | fi 76 | 77 | exit 0 78 | --------------------------------------------------------------------------------