0

So I have many commits in the master branch. I want to roll back to a commit and make some changes in one file. It's simply to do with checkout command.

So what were my steps. 1. I've checkout new branch from master git checkout -b new_branch 2. Then in new_branch I made git checkout f95ecfe to roll back to a commit.

Now it says: HEAD detached at f95ecfe

On this stage I want to add some changes and push this new branch to the bitbucket.

Should I do some other actions or I can simple make git push origin new_branch

Also in the master after this commit f95ecfe I have many other commits, so my question also how can I correctly merge this new branch with detached head with a master. Will it just merge one my modified file or it will merge entire tree from new branch with have different state of all files with master tree?

Matrosov Oleksandr
  • 25,505
  • 44
  • 151
  • 277

2 Answers2

2

You should think of a pushed master as being sacred (unless you're the only one editing it). Otherwise, if you start reordering master, (ie you go back in time, change commits, and "force push" them), then you are effectively re-writing history. Anyone else who has pulled master will then have inconsistencies when they pull again, and have to sort them out. Total pain.

There are a few different approaches to keeping a 'nice master', depending on your preference / who you're working with.

The following is how I'd recommend dealing with your situation in these cases:

Linear Master

My preference is a linear master - so this would mean that whenever anyone pushes, they first rebase on top of master, and then push. Master is then a straight line, and you don't get lots of branch merges confusing things.

What you should do is simply add a commit fixing the file at the end of your master, and push that, identifying in the commit message which previous commit you're modifying etc.

That is, you do something along the lines of:

git checkout master
git add FILE_TO_CHANGE
git commit -m 'Bug fix for f95ecfe (Plus more details, obviously)'
git push origin master

(Optionally, create a bug fix branch to work off, then delete it later, a full workflow might look something like):

git pull --rebase origin master //Pull latest code
git checkout master // Move head to master (and check it out)
git checkout -b bug_fix // Create branch and check out to it (currently pointing to the same commit as master)
// Do some work...
git add FILE_TO_CHANGE
git commit -m 'Bug fix for f95ecfe (Plus more details, obviously)'
git pull --rebase origin master // Pull latest code, try to rebase on top of it
git checkout master
git merge bug_fix // fast-forward merge master onto bug_fix branch
git push origin master // push master
git branch -d bug_fix // delete the temporary local branch

Branched master

A branched master allows you to see more clearly which commits are related, but means it can look pretty messy. Some people prefer this approach though.

The work flow would then be something like:

git pull origin master
git checkout f95ecfe // Move head to f95ecfe (note: HEAD is no longer on a branch! - just a commit)
git checkout -b bug_fix // Create branch at the current position and check out to it (branch is pointing to f95ecfe)
// Do some work...
git add FILE_TO_CHANGE
git commit -m 'Bug fix for f95ecfe (Plus more details, obviously)'
git pull origin master // Pull latest code. ALSO merges onto master.
// Alternatively could do:
git merge master

git checkout master // Now we need to bring master up to where we are
git merge bug_fix // fast-forward master onto the bug_fix merge
git push origin master // push master
git branch -d bug_fix // delete the temporary local branch

If you really do want to go back in time and force master

If only you edit master and you want to go back in time and change the commit, and change it on master, do the following:

git checkout f95ecfe
git checkout -b 'bug_fix' // It's nicer to have your head attached to a branch. So create a branch at this point

// Make some changes
git commit --amend 'Message'

Now you need to add all the other commits onto where you currently are. There are quite a few ways of doing this. Personally, I prefer to use the cherry-pick command through git gui to do this step by step, instead of doing one massive rebase. But the cleanest thing to do is a rebase of master onto bug_fix as follows:

git checkout master
git rebase --onto bug_fix f95ecfe // Put the commits from (but not including) f95ecfe up to master, on top of bug_fix

You should then check everything looks like it aught to in git gui, and then you can push:

git push -f origin master

NOTE: As stated before, this is a FORCED push with -f. Don't do this if anyone else has a copy of the master branch on their machine, as it will make their copy inconsistent, and cause them much misery as they have to rebase all their changes and fix their local master.

PS: There are many ways of doing this section, I give the way I think is most simple (in the sense that it uses more basic commands). Alternatives include making a commit on top of master (as per the linear master instructions) and then using git rebase -i (interactive mode) to re-order the commits <- this is perhaps the most natural way to do it.

David E
  • 1,384
  • 9
  • 14
0

You can create a branch in the state that you are in and then perform your actions just like any other branch.

The detached head state just means any changes that you make aren't on a branch and could be lost if you were to go to a branch. So you can go ahead and make your changes and commit them. Then to send them to the remote do the following:

//Create a branch at your current state.
// you can also do this before committing.
git branch <new branch name> 
//Send it to the remote.
git push origin <new branch name>

Now your changes are just like any other branches. If you wanted to bring your changes into master all you need to do is git merge and resolve any conflicts that occur because of your change.

This page has an explanation of detached head. Basically, you are exploring the code in your local repo. But if you change to a branch, your commits are just floating around. They aren't part of a branch to be referenced and will be garbage collected at some point. In order to retain the changes, you just need to create a branch that your commits can be part of.

Schleis
  • 41,516
  • 7
  • 68
  • 87