Reputation: 521
I have a commit on my feature branch, consisting of 3 files, one of which now has a merge conflict with master.
I'd like to:
I've tried reverting but this works on the whole commit not the single file.
I've tried checking out the single file (at its revision prior to the commit I want to roll back) and committing that (to essentially revert the single file). However when I rebase the conflict still happens.
I feel like I need to do a hard reset on this single file somehow but I can't see a way of resetting an individual file.
Upvotes: 3
Views: 1693
Reputation: 25835
You can use git checkout
to get a single file from another commit like so:
git checkout <commit> -- path/to/file
To prevent the conflict, you should squash the new commit into the previous (conflicting) commit.
A rebase will apply each commit in the list, one at a time. If you have a conflict, then every single time you rebase you will have to re-address that conflict. That's one reason that I prefer a good ol' merge. Merges happen at the top of the stack (so your anti-conflict commit will apply), and any conflicts you do run into only need to be solved once.
If you really want to use a rebase, then you can git rebase -i HEAD~N
(where N is however many commits you need to go back to get to the conflicting commit) then edit that commit directly (place an e
next to it in the editor) or squash the second commit into the first (place an s
next to the new commit). Basically, you need to change your commit history. Then you should be able to rebase off master.
Upvotes: 5
Reputation: 45689
The problem here is conceptual: you're taking commands that apply to commits, and trying to apply them to files, and this is skewing your reasoning about how to address the problem at hand.
To clarify: files are not committed individually. Each commit has a single TREE
, which represents the state of the entire project content. You change three files, this creates a new state of the content; you git commit
, this creates a single new COMMIT
object with a TREE
representing the new state of the project.
Perhaps the confusion comes from familiarity with other source control tools. The commit model used by git
is in contrast to CVS, where changes are committed to individual versioned files, for example.
So if you roll back using something like reset
, you undo all of your changes. If you rebase
to get changes from master
, you get all of the changes from master.
This doesn't mean you can't get where you want to go; you just have to approach it a bit differently.
The simplest (and IMO most correct for the situation) thing to do is to resolve this during the merge operation. Once get tells you there are conflicts, you can get master
s version of the one conflicting file
git checkout master -- path/to/conflicting/file
Then you can use whatever editor or IDE you're using to manually re-apply your changes. (You can always git diff HEAD
git merge-base HEAD master-- path/to/conflicting/file
if you need to review the changes you originally made.) Then
git add path/to/conflicting/file
to mark the conflict as resolved, and
git commit
to finish the merge.
Upvotes: 1