Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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:

  • roll back the commit on the conflicted file
  • rebase from master onto the file that had the conflict
  • manually reapply my rolled back changes on that file

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.

like image 383
andrea Avatar asked Jan 27 '26 05:01

andrea


2 Answers

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.

like image 75
JDB Avatar answered Jan 29 '26 20:01

JDB


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.

like image 45
Mark Adelsberger Avatar answered Jan 29 '26 19:01

Mark Adelsberger