1

I have a git setup with two repositories, both of which are read/write (I usually code on one, but sometimes I code on the other too). My workflow is typically that I do work on my local repo, and then when I'm ready to test my changes, I push my commits to the other remote repo where I actually build my project. For some reason, however, when I push from local to remote, the changes on the remote repository are "inverted", i.e. the repository is updated, but the inverse of the changes (i.e. the changes that would bring the remote repo back to its pre-pushed state) are registered in the index.

For example, say I have a file with a comment // This is a comment that I've updated to say // This is a comment that has been updated locally, and then pushed to my remote repo, I get the following on my remote repo:

remote_repo$ git diff --cached
-// This is a comment that has been updated
+// This is a comment

Obviously I can bring them into the same state by running git reset --hard, but is there any other way to do this and/or automate it? I expect most people will suggest adding a post-receive hook that runs git reset --hard, but I'm hoping this is configurable in a clean way.

Byte Lab
  • 1,576
  • 2
  • 17
  • 42
  • Side note: what's in the index at this point is whatever was in the index *before* the push. That's the source of the problem: the index matches what used to be the `HEAD` commit, but `HEAD` itself has changed in some way, and now resolves to a new, different commit. You don't need a hard reset (a mixed reset suffices) but in general this is a bit of a trap. – torek Sep 22 '17 at 18:49
  • Doh, that makes total sense in retrospect. I realize that it's an awkward workflow but I own both repos and neither are accessed by anyone else so the danger is really just an inconvenience. – Byte Lab Sep 22 '17 at 19:54

1 Answers1

2

Presumably you're pushing to the branch that's currently checked out on the other repo.

The applicable config option is receive.denyCurrentBranch. It's original purpose (and I believe the current default... so I'm surprised if you haven't come across this option before) was to avoid the "inverse changes in index" situation by simply rejecting pushes that would update the current head.

As long as you keep the work tree on the "other" repo clean, there's no reason you can't have your cake and eat it to. If you set receive.denyCurrentBranch to updateInstead, then git will go ahead and update the head and then do a checkout to sync the index and work tree - as long as they're clean going in.

If you want to live dangerously, you can configure around even that restriction using the push-to-checkout hook.

UPDATE - Wasn't thinking about this angle since linked working trees weren't mentioned in the question, but as torek points out: if you are using linked working trees (i.e. git worktree add) in the repo receiving a push, the receive.denyCurrentBranch setting will not protect the branch to which a linked working tree is checked out; only the main working tree is protected. If needed, I imagine you could write a post-receive hook to mimic the behavior of updateInstead for linked trees.

Mark Adelsberger
  • 42,148
  • 4
  • 35
  • 52
  • One should also be aware that push interacts badly with `git worktree add`: https://stackoverflow.com/q/41158057/1256452 – torek Sep 22 '17 at 18:47