Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Advanced git scenarios

Tags:

git

I have several advanced scenarios I would like to solve, but I don't know how. I hope you can help:

  1. A - B - C - D - E. I would like to add the changes from commit D into commit B and remove commit D. How?
  2. A - B - C. Commit B contains a file that should not have been committed. How to remove it from the commit?
  3. A - B - C - D. Commit C contains a file that should have been committed with commit B. How to remove it from commit C and add it to commit B?

Please note: All commits are in my working copy only and have not yet been pushed.

like image 396
Daniel Hilgarth Avatar asked Nov 06 '11 00:11

Daniel Hilgarth


1 Answers

My answers use git rebase quite a lot. If you're new to rebasing, be sure to read this chapter on git rebase first

  1. git cherry-pick B Like you found out yourself, you could rebase -i A and swap the C/D revisions, squashing B+D together.
  2. git rebase -i B, mark B as edit and apply changes.

    Now to really remove the objects from the object database you may need to use filter-branch on all branches containing the object. After that, it may take a while for reflogs to expire. If the object is a security sensitive one, you may want to git gc --aggressive --prune=tomorrow. The Pro Git book has a section on removing objects.
    With git-filter-branch always remember to include --tag-name-filter cat, see comments

  3. If all of C should be in B, simply

    git rebase -i B mark C with squash and it will squash the commits together.

    If it gets any more involved than that (only a single file from C needs to go in B), I'd split the job into smaller steps that can be solved as in the above steps:

    • split commit C in two parts: one (C.1) to merge into commit B and one (C.2) to keep as the new 'C'. E.g. from the Git Pro chapter linked above:

      If you wanted to split a commit, for instance, you would specify 'edit' for that commit:

      pick   fc62e55 added file_size
      pick   9824bf4 fixed little thing
      edit   21d80a5 added number to log
      pick   76b9da6 added the apply command
      pick   c264051 Revert "added file_size"
      

      And then when you get to the command line, you revert that commit and create two (or more) new ones. Lets say 21d80a5 modified two files, file1 and file2, and you wanted to split them into seperate commits. You could do this after the rebase dropped you to the command line :

      $ git reset HEAD^
      $ git add file1
      $ git commit 'first part of split commit'
      $ git add file2
      $ git commit 'second part of split commit'
      $ git rebase --continue
      

      And now instead of 5 commits, you would have 6.

    • rebase to merge commits B and C.1
like image 183
sehe Avatar answered Sep 21 '22 21:09

sehe