andrea
andrea

Reputation: 521

How to roll back (reset) a committed change in git on a single file

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

Answers (2)

JDB
JDB

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

Mark Adelsberger
Mark Adelsberger

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 masters 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 HEADgit 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

Related Questions