Roman
Roman

Reputation: 131298

How to combine many commits into one and then split them in two or three?

In my local repository I have made many changes to the code. While doing that I pulled several times, created different branches, committed many times, merged and so on. However, the good thing is that everything that I did, I did only locally. I never have pushed to the remote repository. So, in spite on all the intricate actions with the git that I have performed, I still have a very simple mental picture: (1) there is the code on the remote repository and (2) there is code that I have locally. Now, I want to clean everything up by doing the following:

  1. I want to see what is the difference between the code on the remote and local repositories.
  2. I want to pack all the changes that I have together, so that they look like coming from one commit (with one commit message). I do not want all my commit messages, that I have generated so far, to go to the remote repository.
  3. I might also want to split my changes in two or three parts (each one coming as a separate commit with the corresponding commit message).

Is it possible to do it with git? And, if it is the case, how can I do it?

Upvotes: 1

Views: 145

Answers (3)

mkrieger1
mkrieger1

Reputation: 23313

Suppose you are in the following situation:

 o--o--o--o--o--o--o [remote branch]
        \        \  \
         o--o (... lots of commits ...) o--o [your branch]

To find out the differences between your local branch and the remote branch, use

$ git diff <your branch> <remote branch>

To create one or more commits, applying your work on top of the remote branch, do the following:

  1. Create and switch to a new branch at the same commit that the remote branch already points to:

    $ git checkout -b <new branch> <remote branch>
    

    This results in:

     o--o--o--o--o--o--o [remote branch] [new branch]
            \        \  \
             o--o (... lots of commits ...) o--o [your branch]
    
  2. Copy the differences between the new branch and your existing branch to the index, preparing a new commit:

    $ git checkout -p <your branch>
    

    Once you are satisfied, create a commit:

    $ git commit
    

    Resulting in:

                         o [new branch]
                        /
     o--o--o--o--o--o--o [remote branch]
            \        \  \
             o--o (... lots of commits ...) o--o [your branch]
    

    Repeat git checkout -p and git commit until there are no more differences between the new branch and the existing local branch:

                         o--o--o--o [new branch]
                        /
     o--o--o--o--o--o--o [remote branch]
            \        \  \
             o--o (... lots of commits ...) o--o [your branch]
    
  3. Push your new branch to the remote repository, or make a pull request, or whatever the workflow of the project is.

Upvotes: 1

djuarezg
djuarezg

Reputation: 2541

git rebase will help you.

To split apart your most recent commit, first:

$ git reset HEAD~

You can commit then the different pieces you want.

For joining different commits you can use use squashing finding the commit hash you want to squash on top of and then use:

git reset *mentioned_hash*

Upvotes: 0

Emil Kantis
Emil Kantis

Reputation: 1114

  1. git fetch --all && git diff master origin/master
  2. git checkout -b new-master && git branch -D master && git checkout master && git merge --squash new-master
  3. same as above, but before going back to master you should use git rebase -i to rewrite to history of new-master

What 1 does is simple: gets latest changes from the remote repository and compares your local changes to it. Assuming that master is the branch you want to compare.

What 2 does is more complicated. It creates a new branch out of your local changes, followed by deleting your local master (again, assuming this is your working branch). After that, it checks out master again, which gives you a copy of the remote repository's master branch. Then, git merge --squash combines all your changes from new-master and adds them onto master

Regarding 3. I suggest you read up on git rebase

Upvotes: 1

Related Questions