2

Say I have this sequence of commands:

current_branch="$(git rev-parse --abbrev-ref HEAD)"
git checkout -b "foo"
git lock "$current_branch"   # i made this up

what I want to do is lock a branch so that I cannot accidentally make changes to it after I am done with it. For example, after a feature branch has been squashed and merged into the integration branch.

Is there a way to do this with git? Perhaps there is a way to lock a worktree using https://git-scm.com/docs/git-worktree?

Alexander Mills
  • 90,741
  • 139
  • 482
  • 817
  • 1
    What's your reason for needing this? Could a tag work just as well? See `git tag` – Adam Sep 01 '18 at 01:08
  • 2
    You could just do the low-tech "copy or rename the branch and append 'lock' to the end of the branch name" and just not touch that branch. If you don't want to make a change to a local branch, then don't don't make a change to the local branch. Do you really need to force yourself to not modify it with a locking mechanism here? – Matt Messersmith Sep 01 '18 at 02:58
  • yeah honestly it would be helpful, if I changed to a temp branch and then modified all the file permissions to read only or something. I make changes to the wrong branch all the time. Once I am done with a feature branch and it gets merged, I accidentally continue working on that feature branch all the f-ing time, it kills me lol – Alexander Mills Sep 01 '18 at 03:27
  • @MattMessersmith: yes, except that branch names are forbidden from ending with the string `.lock` (see `git check-ref-format`). (You might start with `locked.` instead.) – torek Sep 01 '18 at 04:41
  • 1
    Possible duplicate of [Is there a way to make a local branch immutable?](https://stackoverflow.com/questions/36102161/is-there-a-way-to-make-a-local-branch-immutable) – phd Sep 01 '18 at 12:44
  • The OP explains the use case - I want to prevent myself from accidentally working on a feature branch which has already been squashed and merged into the integration branch. – Alexander Mills Sep 02 '18 at 02:14
  • The easiest way is to create a tag on the branch tip and remove the branch altogether. Use a consistent rule to name these tags to let them explain their purposes and you're done. – axiac Sep 02 '18 at 08:24

2 Answers2

3

How about we roll this feature ourselves? Lets start with your git lock command. We can write that as an alias;

$ git config alias.lock "! touch .locks;
    git rev-parse --abbrev-ref HEAD | cat - .locks | sort | uniq > .locks.tmp;
    mv .locks.tmp .locks;"

Whenever we call git lock we're going to add the current branch to the .locks file which is our distinct list of locked branches.

Then create (or edit) .git/hooks/pre-commit to include;

#!/bin/sh

if grep -Fxq `git rev-parse --abbrev-ref HEAD` .locks
then
    cat <<\EOF
Error: Branch is locked
EOF
    exit 1
fi

Which will check the .locks file each time we commit to make sure we're not commiting to a locked branch.

Add an entry in your .gitignore to ignore our new .locks file and you're done.

Example usage;

adam@lime ~/git-lock $ git checkout -b MuhBranch
Switched to a new branch 'MuhBranch'
adam@lime ~/git-lock $ git commit -m "Final changes." --allow-empty
[MuhBranch 0304f21] Final changes.
adam@lime ~/git-lock $ git lock
adam@lime ~/git-lock $ git commit -m "Just one more..." --allow-empty
Error: Branch is locked

Remember to make your .git/hooks/pre-commit executable using chmod u+x .git/hooks/pre-commit.

Adam
  • 4,180
  • 2
  • 27
  • 31
  • small typo: you wanted `git rev-parse` not `git ref-parse` (this is a typo I make myself all the time...). – torek Sep 01 '18 at 04:42
1

To lock a branch, you can use git hooks. Check out this SO.

#!/bin/sh
# lock the myfeature branch for pushing
refname="$1"

if [[ $refname == "refs/heads/myfeature" ]]
then
    echo "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
    echo "You cannot push to myfeature! It's locked"
    echo "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
    exit 1
fi
exit 0
jaychang0917
  • 1,880
  • 1
  • 16
  • 21