I have a Visual Studio solution that includes 12 projects. The code is hosted on Azure DevOps using git
. I’ll admit I’m not an expert of git.
I’ve created some branches from the "master" branch. I kept working normally both on the new branches and on the master, making some commits.
Then, unfortunately and without thinking, I moved some projects from their folders to other folders and then kept working on branches and merging them into master, without noticing anything. Then I realised that some files were missing, some changes made previously were gone and some files contained unwanted changes. Probably this happened after I merged branches into master after I moved projects…
Now my question is: is it possible to remove the commit that moved projects into other folders, applying the changes of the subsequent commits? How?
3
Answers
You can do this by reverting those commits
First I would recommend you to do all this changes in a separate branch:
git checkout --branch revert-unwanted-changes
then you will want to identify the SHA of the commits you want to revert
git log
Copy the
sha
of the commits you want to revert (sha is the alphanumerical 40 char identifier that every commit has) and revert them bygit revert <commit-sha>
once you’re happy with the changes, merge back to main
Answer already given in old post How do I revert a Git repository to a previous commit?
With reset command you can rollback your changes like this
git revert –no-commit 0d3f8dc4..HEAD
git commit
Part of this depends on what you want the history to look like.
your history looks (very roughly) like this right now.
Here are some possible "fixes". 1:
this is what ‘git revert bad_change_guid’ would do.
2:
This would be creating a new branch without the bad change, applying every change on it, then merging MAIN into it.
3:
This is "deleting bad change from ever happening".
If you are working totally locally, it is possible that you want to do #3. It has the disadvantage that it rewrites history. If you aren’t working totally locally doing #3 is very hostile.
#2 is like #3, except it keeps history intact. You create an "alternative universe" in which the changes after the bad change occurred without the bad change. Then you merge the bad history over to the new, corrected history.
#1 is by far the simplest. Here, you create a CL that represents undoing the bad change, and you apply it today.
By default you should probably do #1. To use it, you need to find the identifier of the bad change (its guid or other identifier). Then you need to do "git revert IDENTIFIER" to create a commit that attempts to undo it.
You’ll then have to manually inspect this change and the result of it to determine if it did everything correctly.
The way I’d do #2 would be to first create a new branch on top of main. Then I’d do an interactive rebase to strip bad_change out of the history (using
git rebase -i bad_change_id~
). Test the result, then do a merge of main into this branch, but for all conflicts take the branch version. Then push the resulting merge history up to your remote repo.To do #3, you’d do the interactive rebase to strip out the bad commit, then you’d push the new MAIN branch up to the remote repo.
#3 is highly hostile to anyone else, because their work is now going to be on top of changes that no longer exist. In addition, rewriting history is dangerous: if you screw up again, you won’t be able to undo the screw up nearly as easily.
Both #2 and #3 are significantly trickier to do right than #1.