What is the exact incantation to tell git to go ahead and do it?
The form of the question suggests that there is only one command that is correct. That's not the case. Any set of Git commands that wind up with that file in Git's index under that pathname will suffice.
Based on what you have shown:
git add new/path/to/some/file.spec.js
should suffice. If this doesn't work, though, or goes wrong, read on.
Long
The thing to understand here, the deep (or, well, less-shallow? ) magic in Git, is that when a merge1 stops with merge conflicts, what Git has done is to leave the conflicts in Git's index. Your job is now to repair the mess in the index.
The index, which is also called the staging area (or sometimes the cache), contains a series of name-and-hash-ID pairs, which you can see with:
git ls-files --stage
The names are the names of the files that will, or would, go into your next commit. The hash IDs are Git's internal identifiers that record the corresponding file content.
Normally, each entry is at stage number zero, and the output from git ls-files --stage
looks like this (I've snipped just a few pieces of output from the command run in a Git repository for Git):
100644 b08a1416d86012134f823fe51443f498f4911909 0 .gitattributes
100644 536e55524db72bd2acf175208aef4f3dfc148d42 0 COPYING
100644 80d1908a44ca38058c58dcc4e3444ee96060757b 0 Documentation/Makefile
100644 7074bbdd53cc1141c75546ad6e009b5ac74a63c2 0 wt-status.c
100644 35b44c388edf0cd75cca00e1458b9995c8001538 0 wt-status.h
The 100644
s denote the file mode (not-executable), the hashes record the content, the zeros by themselves are the stage number, and the rest of the line is the pathname, possibly including embedded (forward) slashes, as in this case for the Documentation/Makefile
file.
If one were to run git commit
right now, the new commit would contain exactly the set of files listed here. However, git commit
itself will balk—fail—if any of those stage numbers are nonzero.
When git merge
runs, it expands the index, filling in a lot of nonzero stage numbers. It then performs the merge, and each successful merge resolves a file and moves it back to stage zero, collapsing away the nonzero stage entries. Each failed merge leaves the nonzero stage entries in place.
The git status
command separates out the stage-zero paths (which are staged for commit
) from the nonzero-stage ones. Anything in staging slot #1 is a merge base file, that came out of the shared common commit. Anything in staging slot #2 is from the HEAD
commit, and anything in staging slot #3 is from the other commit.
The path names may be modified by the merge operation, by picking up a rename request, but the file content might be from your HEAD
commit. There might in fact be no file from their commit, so that staging slot #3 is empty, and if the file wasn't in the merge base either, staging slot #1 will be empty as well. In this case, you'll see this file listed as added by us
. That's true even if the path name got changed somehow.
The git add
command tells Git: make the index entry for this pathname match the work-tree file of the same pathname. This has the side effect of removing any stage 1, 2, and 3 entries for that path name, resolving conflicts. It adds the file at stage zero, or if the file is missing from your work-tree, just removes all the index entries for the file. Either way, there are no longer any nonzero stage number entries.
Most Git merge cases are pretty simple, but any time there are massive renames, or a directory gets renamed, things get messy. The path name of some file was old/path/to/file
in the merge base. It may be old/path/to/file
in your own commit—the one you're copying, via git rebase
, to a new-and-improved commit—or it might be third/name/for/file
, and the path you want is new/nameoffile
or whatever. Whether and when Git puts the right path in some index slot is a bit iffy. There has recently been a bunch of work to improve this, and based on the messages you quoted, I think you have a newer Git.
All ("all"?) you really have to do here, though, is arrange for Git's index to hold the complete right set of file names and content hashes. Whatever is in Git's index, at stage zero, is what will go into the new commit when you run git rebase --continue
. All of this stuff about conflicts, added by us, added by them, and so on is just a way to describe what's in nonzero staging slot numbers. Everything that shows up under changes to be committed
is in staging slot zero, and is showing up there because it's different from what is in the commit that is currently HEAD
.
See also footnote 1, for which I'll call this answer "done" now and proceed to write it ("it" being the footnote).
1You're running git rebase
, not git merge
. But rebase uses git cherry-pick
, and git cherry-pick
uses Git's merge engine. The trick here is that when rebase does each git cherry-pick
, you're on a new branch that Git is building in place, that will be renamed to be your branch. This new branch starts out with the same last commit as their branch, the one you're rebasing onto. So when you see "added by us", it means "added by someone(s), somewhere along the way, starting from what they started with" and that might be them rather than us. It's extra-messy because by the time you're ten or twenty commits deep in the rebase, the "ours" or HEAD
commit that Git is working with is a ten or twenty commit deep mix of your copied commits and their originals.
The gist of all this is that you should pay less attention to the annoying apparent reversal of "us" and "them" here sometimes, and just concentrate on resolving conflicts by putting together the final snapshots you want for each commit. I find setting merge.conflictStyle
to diff3
helps, too.