tags:

views:

284

answers:

3
+1  Q: 

Git Rebase Help

After quite a few hours playing with rebase, the repo still looks different from what I need:

I would like to accomplish the following tasks
[some of which were OK before I started messing with rebase :( ]

  • Move The top commit ("Removed extraneous...") to before the branch off (Right above "fix for #226").
  • Combine the two commits that are in the 'twist/main' branch.   "comma" and "Moved loaded..." should be the same commit, and I don't need the commit message of "comma" at all.
  • Merge the newly combined "Move loaded" commit into the 'backup' branch, and get rid of 'twist'.
  • Move 'master' to where it now says 'backup'.
  • What does that "remote/origins/master" tag mean?

alt text

I realize that this is asking a lot, but please include actual GIT commands.

I don't mind reading and trying on my own, but am a bit confused by the results not matching what I would've expected, and I really don't want to accidentally destroy any commits.

+3  A: 

First, re-ordering the backup commits.

# Safety, should be a no-op if your gitk snapshot is accurate
git checkout backup

# Temporary branch
git branch backup-save backup

# Move top commit onto 'Fix for #226:
git rebase --onto origin/master HEAD^

# Go back to saved branch's parent (i.e. without the moved commit)
git reset --hard backup-save^

# Rebase onto the moved commit (HEAD@{1} is where HEAD was 1 step
# ago i.e. before the reset.)
git rebase HEAD@{1}

# Don't need the saved branch any more (although you might want
# to keep it for a bit just in case). This deletes it:
git branch -D backup-save

Combine the two commits on twist, ignoring the top commit message.

git checkout twist

git reset --soft HEAD^

# Just re-save the commit message, alternatively to skip the
# editor step do this: git commit --amend -C HEAD
git commit --amend

Merge the twist branch into backup, remove the twist branch.

git checkout backup
git merge twist
git branch -d twist

Move master. There are multiple fancy ways, but this is simplest. I'm assuming that you want master to point to the edited backup position and not where it originally was.

git checkout master
git reset --hard backup

remote/origins/master is the remote tracking branch and tells you where the branch pointer for the master branch in the remote repository origin is, or rather was when you last fetched, pushed or pulled.

Charles Bailey
Wow, you are good. 1. The 'git checkout twist' steps did not succeed in combining the two commits in the twist branch. Was it suppposed to, or am I missing something?<br>2. At 'git merge twist'. It complains: CONFLICT (content): Merge conflict in Source/Depender.jsAutomatic merge failed; fix conflicts and then commit the result.<br>How do I fix the conflicts?
SamGoody
Wait, I know to fix the conflicts with git add. Will report back in a minute, either further messed up, or all happy.
SamGoody
While I didn't quite get those two steps to work, it got me close enough to achieve the objective. Everything you wrote was clear and to the point. Thanks very much.
SamGoody
+1  A: 

How to Not Be Afraid

I'd like to show you that no matter how bad you mess up, commits never get destroyed* and you can always get back to where you started.

I've made a faux git tree that has the same shape as you illustrated:

I am now going to wipe out the last three commits from the 'backup' branch:

$ git log --oneline
9b41f46 Removed extraneous whitespace
981e2e8 Merged the "loadscripts" function
005bc62 Pick up a few very fringe cases
07e71d9 Merged "getDepsForScript" function
...
$ git reset --hard HEAD~3
HEAD is now at 07e71d9 Merged "getDepsForScript" function
$ git log --oneline
07e71d9 Merged "getDepsForScript" function
...

Oops, that was bad. Let's get back to where we started. First see what we did:

$git reflog
07e71d9 HEAD@{0}: HEAD~3: updating HEAD
9b41f46 HEAD@{1}: commit: Removed extraneous whitespace
...

You can see that when we reset, all git did was to make HEAD point to that old commit. But no commits were actually lost--they just became orphans, not part of any branch. Let's make them part of the "backup" branch again:

$ git reset --hard 9b41f46
HEAD is now at 9b41f46 Removed extraneous whitespace
$ git log --oneline
9b41f46 Removed extraneous whitespace
981e2e8 Merged the "loadscripts" function
005bc62 Pick up a few very fringe cases
07e71d9 Merged "getDepsForScript" function
...

Git means never having to say you're sorry.

*Loose objects do eventually get garbage collected, but not until they are at least two weeks old.

How to Do What You Want.

First let's combine the two commits in master:

$ git checkout master
$ git rebase -i HEAD~2

Git will launch your editor. Change this:

pick 6389f4e Moved "loaded" function out of "require".
pick 41fb646 comma

to this:

pick 6389f4e Moved "loaded" function out of "require".
s 41fb646 comma

And save. Git will again launch your editor. Change this:

# This is a combination of two commits.
# The first commit's message is:

Moved "loaded" function out of "require".

# This is the 2nd commit message:

comma

to this:

Moved "loaded" function out of "require".

and save.

Now let's reorder the commits in 'backup':

$ git checkout backup
$ git rebase -i remotes/origin/master

When your editor pops up, change this:

pick ec7f71c moved "loaded" fucntion out of "require"
pick 4a76897 Replaced maploaded event
pick 07e71d9 Merged "getDepsForScript" function
pick 005bc62 Pick up a few very fringe cases
pick 981e2e8 Merged the "loadscripts" function
pick 9b41f46 Removed extraneous whitespace             <-----

to this:

pick 9b41f46 Removed extraneous whitespace             <-----
pick ec7f71c moved "loaded" fucntion out of "require"
pick 4a76897 Replaced maploaded event
pick 07e71d9 Merged "getDepsForScript" function
pick 005bc62 Pick up a few very fringe cases
pick 981e2e8 Merged the "loadscripts" function

and save.

Now cherry-pick the merged "Moved loaded" commit off of master and onto the current branch ("backup")

$git cherry-pick master

Make master point to the same commit as "backup"

$git checkout master
$git reset --hard backup

Get rid of the twist branch

$git branch -D twist
Wayne Conrad
I greatly appreciate your work. Very detailed and helpful.
SamGoody
Sam, My pleasure. And that's not just an expression -- I have a lot of fun and learn much when I pick a question on the edge of what I'm familiar with.
Wayne Conrad
+1. Other useful command to get back old commits: fsck (http://freeasinbeard.org/post/318519782/reflog-and-fsck-your-git-disaster-recovery-toolkit)
VonC
A: 

There are a number of things you are trying to achieve here and it's a tad unclear from the diagrams provided exactly what is needed but the following pointers may help:

  • Rather than try to move your branch, I would first combine the commits you've done on that branch, then apply the final commit to the master branch since thats eventually what you are aiming at. You may have to resolve some conflicts at this point but you would have to do that anyway. See the next two tips for info on how to achieve this.

  • To combine two commits you can do aninteractive rebase.

  • To pick a single commit from one branch and apply it to another, whilst on the target branch use git cherry-pick. You can delete the old branch using git branch -D twist when done.

Hope these tips get you on the road to your goal.

jkp