Reputation: 6735
I'm creating a git post-checkout
hook to ensure my database state is consistent as I move between branches, but I'm running into a peculiar problem.
To make this work, I have to access migrations from both the "from" branch and from the "to" branch. The post-checkout
hook runs after the index and work tree have been brought up to date with the "to" branch. What it does is this:
GIT_WORK_TREE=/tmp/from-branch git checkout $from_branch -- db
to get the db files of the "from" branch into /tmp/from-branch/db
.GIT_WORK_TREE=/tmp/to-branch git checkout $to_branch -- db
to get the db files of the "to" branch into /tmp/to-branch
./tmp/from-branch
.This all works splendidly, except that after it runs, git is showing the following:
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: db/migrations/non-prod/20180718_102122-new-one-test-data.sql
new file: db/migrations/schema/20180718_102108-new-one.sql
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
deleted: db/migrations/non-prod/20180718_102122-new-one-test-data.sql
deleted: db/migrations/schema/20180718_102108-new-one.sql
These two files are the files that were checked out from $from_branch
into the tmp work tree. Git seems to be assuming that I'm checking them into my repo (despite my setting the GIT_WORK_TREE
variable to another path) and automatically adding them to the index as "staged". I've combed the git-checkout
manpage for options that would prevent this and haven't found any.
My current best solution is to run git reset
after the checkout, but that feels like a hack. Just wondering if anyone else can think of some better solution.
Upvotes: 1
Views: 489
Reputation: 488183
Your terminology is a little bit off, but this is essentially correct: git checkout
copies files into the index first, before copying them out to the work-tree. This is how it is that the index indexes or caches the work-tree—hence the names the index and the cache. (Git also uses the index's cached information to minimize the amount of actual work done, so that if the files already exist in the work-tree in the correct form, Git does not have to touch them there.)
You are, as you note, using a different, temporarily overridden, work-tree. What you need, then, is a different, temporarily overridden, index. And in fact, Git supports just that:
TF=$(mktemp)
trap "rm -f $TF" 0 1 2 3 15 # clean up on exit
rm -f $TF # Git prefers a non-existent file to an empty one
GIT_INDEX_FILE=$TF GIT_WORK_TREE=/tmp/from-branch git checkout $from_branch -- db
rm -f $TF
GIT_INDEX_FILE=$TF GIT_WORK_TREE=/tmp/to-branch git checkout $to_branch -- db
... proceed as before
Note that rather than removing the temporary index each time, you could, if you choose to keep the /tmp/from-branch
and /tmp/to-branch
work-trees around as permanent work-trees, use two permanent indexes to index those two work-trees.
Upvotes: 4