0

I use a USB stick with a bare git repo to propagate commits from a development PC to a server that is not immediately accessible. One of my teammates committed some changes, and now I must merge.

I made some changes to my dev directory. I committed them; I pushed them to the USB stick. After I moved the USB stick to the computer with repo access the git push failed because it was not a fast forward on the origin. A coworker had done some work and committed his changes and effectively there were now two branches. I then performed a git fetch which pulled my coworker's commits from the origin onto the USB stick.

However, the USB stick with the bare repo still had its refs/heads/master pointing at the changes I had pushed from my dev box to the stick, while the refs/remote/origin/master was pointing at my coworker's changes that I had pulled from the origin onto the stick.

I was able to fetch the changes onto the USB stick, but now I do not know how to merge them onto the dev PC. A plain git merge in my working directory tells me "Already up-to-date." A plain git merge in my USB bare repo tells me "Fatal: This operation must be run in a work tree".

Inside the bare repository of the USB stick git show-ref tells me I have refs/head/master and refs/remote/origin/master, but I do not know the command to execute inside the development tree that will merge my tree with the remote/origin/master changes.

3
  • Just to double-check... do you have the local master branch checked out? What is the output of git status? Is your upstream still origin/master? What does git remote get-url origin say? Maybe your drive letter has changed for the USB stick and git can't find your remote?
    – JDB
    Commented Oct 7, 2019 at 14:53
  • Can you describe in more details the step : "I was able to fetch the changes onto the USB stick" ?
    – LeGEC
    Commented Oct 7, 2019 at 14:58
  • I have expanded the narrative to outline the steps I took to fetch the changes onto the USB stick. As for JDB's questions: The dev PC has master checked out. The USB stick can't have things checked out because it is bare. One upstream is usbf/master, and the other is origin/master. The drive letters are fine. git remote -v gives different answers from the dev PC and from the USB stick, naturally.
    – Mutant Bob
    Commented Oct 7, 2019 at 16:56

2 Answers 2

2

Fetch from the USB-stick repo into your server repo and merge the result.

git remote add USB /path/to/your/mountable/repo    # once
git fetch USB
git merge USB/master

edit: ah, okay, your origin/master changes weren't pushed or mirrored to your USB repo for some reason, you fetched them into a remote there.

git fetch USB +refs/remotes/*:refs/remotes/*

will fetch refs/remotes/origin/master from your USB stick into refs/remotes/origin/master (and likewise with all the USB's remote refs) on yours.

edit: re the +refs/remotes/*: etc, that's a refspec, see the docs for fetch, push and fetch both use refspecs and explain them. It's a source:destination pattern with a leading + for allow-rewrites, Git fills in defaults intelligently enough that it's maybe even too easy to not know it's happening. The default fetch refspec is +refs/heads/*:refs/remotes/origin/*, neatly mapping the remote's branches to the local tracking refs.

Also see the docs for revisions, git tries the spelling you give it, then tries the refs/, then refs/tags, then refs/heads, then refs/remotes prefixes. SO origin/master usually finds refs/remotes/origin/master.

2
  • That does not actually solve the problem. Because USB/master is not origin/master . USB/master is my commits that will eventually become a branch on the main repo.
    – Mutant Bob
    Commented Oct 7, 2019 at 15:20
  • The added bit about the +refs/remotes/* is a syntax I had never seen before. It appears to work. I can not test the syntax for the subsequent merge since I already achieved my goal using a different technique, but I am optimistic it would be something like git merge refs/remotes/origin/master .
    – Mutant Bob
    Commented Oct 7, 2019 at 15:51
0

It seems the root cause of the problem is that my USB stick (which I call usbf) has branch usbf/master which is not the same commit as origin/master. When I pushed my changes to it the stick became sort of a branch relative to origin/master. When I fetched changes from the origin, my USB stick now had two refs, one for each branch.

I was able to accomplish my mission using https://stackoverflow.com/a/45999240/995935 as a starting point.

In the USB stick's repo I did a

git branch -f master c0094ac0

so that now the master on the USB stick is the same as origin's master. This also had the side-effect of turning my chain of commits on the USB stick into an unlabelled branch (I think? Either way it is not a real problem, this is just the USB stick)

After that, I was able to hop into the dev directory and do a git fetch to retrieve the changes and a git merge to merge them. After that a git push onto the USB stick; followed by a change of computers and a git push from the USB up to the main repo got me to the goal state.

If there is an alternate technique that does not require moving branches, I would be interested to learn it.

Not the answer you're looking for? Browse other questions tagged or ask your own question.