-3

I created a branch to do some work on, tried to merge another branch into it, and immediately ran into an insurmountable merge conflict. Clearly the thing to do was abandon the branch and start over.

I tried deleting the branch, but that didn't work, because it was the current branch.
I tried checking out another branch (the branch I'd just branched from), but that didn't work:

error: you need to resolve your current index first 

I had started resolving one of the conflicts, but abandoned it — that is, without committing it. My first thought to resolve the "you need to resolve" error was to do a git add on the file where I'd been resolving conflicts. I did so, then tried the git checkout again. It worked! Hooray!

I was then able to delete the broken branch.

But then I noticed that something was still wrong, because my index was still full of changes deriving from, I presume, the abandoned merge. In other words, git diff --cached generated nonempty output.

So what did I do wrong, and what should I do instead?

Also, I'm sure I'm wrong, but it seems to me that my git checkout still shouldn't have worked, that I still should have gotten something like that "you need to resolve your current index first" error. I would have thought that, after a successful git checkout, git diff --cached would always show nothing.

(The last question, which I'm not asking because I know I should be able to figure it out myself, is how to get a clean index now. Probably git reset, but I've got to double-check that before I try it.)

0

2 Answers 2

3

should git checkout work when the index is dirty?

There's an extensive answer about this behavior.

I created a branch to do some work on, tried to merge another branch into it, and immediately ran into an insurmountable merge conflict.

git merge --abort will abort the conflicted merge and restore your checkout.

So what did I do wrong, and what should I do instead?

  1. git status will often you helpful options in any situation. For example, during a merge conflict it will tell you about git merge --abort.
$ git status On branch main You have unmerged paths. (fix conflicts and run "git commit") (use "git merge --abort" to abort the merge) Unmerged paths: (use "git add <file>..." to mark resolution) both modified: foo no changes added to commit (use "git add" and/or "git commit -a") 
  1. Get in the habit of using git switch instead of git checkout to switch branches. It's safer, simpler, and more informative.
$ git checkout test foo: needs merge error: you need to resolve your current index first $ git switch test fatal: cannot switch branch while merging Consider "git merge --quit" or "git worktree add". 

My first thought to resolve the "you need to resolve" error was to do a git add on the file where I'd been resolving conflicts.

git add will add the conflicted change to the index. This is the opposite of what you want in this situation. You should instead git restore the files to remove their changes.


Remember, a merge conflict in Git is not magic. Git has attempted to automatically merge and decided it needs a human to help. It's just like a co-worker calling you over for help in the middle of a change they're doing. The files Git was able to merge are staged (git add), and the files Git was unable to merge are unstaged with conflict markers. Your job is to edit the files to resolve the conflicts, stage them, and commit.

Similarly, if you want to undo the uncommitted work use git restore or the special command git merge --abort.

Sign up to request clarification or add additional context in comments.

8 Comments

Thanks. Most of this makes sense. I'll spend some time with that other answer — torek's are always gems. But I do understand why checkout should work when the worktree is empty (and I make use of that every day) — it's the index I was puzzled about. I would have assumed that checkout basically implied merge --abort, but clearly my assumption was wrong. (I also figured the checkout would blow away my unnecessary-and-wrong git add.)
@SteveSummit The rule of thumb is Git will strive to not lose your work. Consider if it worked as you described. You're in the middle of resolving that big merge conflict, go to lunch, and when you come back your boss assigns you a new task. You thoughtlessly type git checkout main and poof all your work on the merge conflict is gone. On the flip side, if git checkout can switch to another commit and still preserve your uncommitted changes it will do so. This is handy to move uncommitted changes between branches without having to stash and unstash them.
@SteveSummit you may find this answer interesting in the context of your question.
@Schwern My enduring confusion — I may have to open a second question on this, or at least amend this one — is why git lets you do a checkout with a dirty index at all, and why anyone would want it to. torek's answer might get at the first "why" — I still can't tell — but not the second. Me, I would have expected that after a successful checkout, the index would always be clean. To achieve this, I would have expected a checkout with a dirty index to either fail, or offer to abort the commit.
@SteveSummit The index (aka the staging area) is where Git builds the next commit. Think of the index as a temp directory and git add makes a copy of the work tree file into the index. Changes which are not yet added to the index (which are not yet staged) are "unstaged" and live only in the work tree (the checked out files). Changes which are indexed but not committed are "staged" but "uncommitted", they have been copied to the index but have not been saved as a commit in the commit history.
|
1

I would do git reset --hard <commit> if I wanted to reset both the working tree and the index.

should git checkout work when the index is dirty?

Should you have to care?

The current version of Git should have enough knobs to let you bail out of operations in a sensible manner.

I created a branch to do some work on, tried to merge another branch into it, and immediately ran into an insurmountable merge conflict. Clearly the thing to do was abandon the branch and start over.

No. These were the operations:

  1. Check out a branch
  2. Start a merge

The last operation was the merge. Bail out of that. Most of these stateful operations have the --abort option:

git merge --abort 

Then delete the branch if you don’t need it.

Could you muck about with the state of the repository until it becomes confused about its own state? I would not bet against that proposition. This is what git-rebase(1) could report to you until recently. [1]

No rebase in progress? 

Are we doing a rebase? A merge? Nothing at all? Well, things are getting philosophical when Git is asking you.

It’s best to use the tools in the orderly manner that they were meant for. That way we don’t have wonder about these weird states.

Notes

  1. It was changed from that so-called passive-aggressive style in 2024. Personally I think that it was honestly confused.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.