0

I have a master branch on git. Using EGit on Eclipse, I have downloaded on my local repo and I have made some changes on many files.

I have already made a huge chunk of changes on many tracked files locally, originally planned for one fat commit. These files have not been added to staged yet. The management wants me to split the changes into 2 independent commits, one after another. What are the steps for me to do that? How do I split the local changes into two versions(or two repos?) locally so that I can commit one after another?

I also have some changes in the same file that needs to split into two commits. How can I do that? I heard there is something called git stash but would that help me to work on one commit after another?

I am new to git, so please explain things in simple English and preferably in break-down steps. Thank you very much. Appreciated!

user2526586
  • 972
  • 2
  • 12
  • 27
  • 3
    Does this answer your question? [How do I undo the most recent local commits in Git?](https://stackoverflow.com/questions/927358/how-do-i-undo-the-most-recent-local-commits-in-git) - Then only add the changes you want before committing each time. – evolutionxbox Jun 23 '22 at 14:11
  • 1
    About splitting existing commits, look: [split commit](https://stackoverflow.com/questions/6217156/break-a-previous-commit-into-multiple-commits) For splitting your current work, check out [interactive staging](https://git-scm.com/book/en/v2/Git-Tools-Interactive-Staging) – kadewu Jun 23 '22 at 14:14
  • 1
    This question "How do I make/clone two versions locally and split them?" is out of context and confuse, please review this, remove, or extend with more infos. – Claudio Weiler Jun 23 '22 at 14:14
  • I agree with @ClaudioWeiler - that entire sentence can probably be completely removed. – TTT Jun 23 '22 at 14:33
  • I agree with @evolutionxbox on this duplicate. Note specifically on the accepted answer, step #2 "[ edit files as necessary ] " is how you will handle the changes to a single file that need to be in 2 commits. You'll pull those changes out for the first commit, and put them back for the second commit. Or, take a look at [how to stage hunks](https://stackoverflow.com/q/1085162/184546) if you have a lot changes to split up. – TTT Jun 23 '22 at 14:36
  • @TTT This question is tagged with Eclipse and with EGit and using Eclipse would be much easier than using the command line. – howlger Jun 23 '22 at 18:46
  • @evolutionxbox You refer to a question how to do the same on the command line rather than in Eclipse. Even if it is doable on the command line, it is easier and more intuitive in Eclipse. – howlger Jun 23 '22 at 20:13
  • @howlger perhaps you wish to add an Eclipse-centric answer? That may be a good addition. Or, perhaps it's similar to [this question](https://stackoverflow.com/q/25304372/184546). – TTT Jun 23 '22 at 20:34
  • @TTT That question is one part and the other would be what is called _Interactive Rebase_ in Eclipse. Probably the question will be closed soon by people who only use Git on the command line, not knowing about EGit. Unfortunately, this happens very often with questions about EGit, even if the questions are clearly tagged as here. – howlger Jun 23 '22 at 20:50
  • @howlger you bring up a good point about the close vote and how the question is tagged. I was one of the close votes and just retracted it. I personally think there is a benefit for anyone learning Git to be comfortable using the command line, since UIs and IDEs come and go and most developers use different UIs throughout their careers. That being said, I do see the benefit of similar questions with different Y values for: "How do I do X in IDE Y?" – TTT Jun 23 '22 at 21:13
  • @TTT Thanks. IMHO better learn the concepts of Git than cramming command line commands. For example, in Eclipse's _Git Interactive Rebase_ view, reordering commits makes it easy to understand e.g. how a Git commit differs from an SVN commit. Maybe it's just me, but I soon forget command line commands if I don't use them regularly. I need _Interactive Rebase_ that rarely, I would have to relearn all the commands each time. The _I_ in _IDE_ stands for _integrated_ and switching to the command line is the opposite of that. – howlger Jun 23 '22 at 21:42
  • @howlger actually, I downloaded Eclipse and EGit earlier this week for the first time just to check it out, and I was happy to see I could open a Git Bash prompt within it. (I think it was called Terminal?) IMHO, **that** is integrated, at least for my use case. – TTT Jun 23 '22 at 21:52
  • @TTT Sure, you can stick to that ineffective and error prone way you're used to. You will not go missing what you do not know. – howlger Jun 23 '22 at 22:23

2 Answers2

2

You are lacking all git basic concepts, my first suggestion is to get some basic tutorials and try. Here one from git docs: https://git-scm.com/docs/gittutorial.

Always good to use an cheat sheet, too. See this one https://www.atlassian.com/git/tutorials/atlassian-git-cheatsheet.

Now, for your questions:

The management wants me to split the changes into 2 independent commits

Commits are always independent, so:

  1. make some work
  2. add that work to staging area
    git add <file_name>
  3. and commit
    git commit -m "<commit comment>"
  4. add more work to staging area
    git add <file_name>
  5. and commit
    git commit -m "<commit comment>"

I also have some changes in the same file that needs to split into two commits. How can I do that? I heard there is something called git stash but would that help me to work on one commit after another?

This one is more trickier. It will depend on what types of changes you have and if your file is tracked or not, but I would go for:

  1. get diff of changed file
    git diff <file_name> > <file_name>_changeset_1.diff
  2. make a copy of diff file
    cp <file_name>_changeset_1.diff <file_name>_changeset_2.diff
  3. edit both diff files, and leave each one with only desired changes
  4. apply change set 1
    git apply <file_name>_changeset_1.diff
  5. commit
    git commit -m "<commit comment>"
  6. apply change set 2
    git apply <file_name>_changeset_2.diff
  7. commit
    git commit -m "<commit comment>"

Obs. I don't revert any previous commit here, if you are talking about reverting commits, pushed or not, than you need to use additional steps.


Edit

As @kadewu mentioned, there is a more easy way to staging the diffs selectively with git add -p <file_name>and using s to split the hunk in smaller hunks.

Claudio Weiler
  • 589
  • 2
  • 15
  • Thank you for your answer. It is very useful. The last part where splitting the changes makes a lot of sense to me. However, is there a more tidy/manageable way of doing this if there are many files, all mixing changes of both commits? – user2526586 Jun 23 '22 at 15:26
  • If you have a lot of files with mixed changes, then I can't see a simpler way. You can use stash like @cb2 answer, but when applying changes from stash you need to remember what you have changed to selectively excluded undesired changes, with diff files you see exactly what's changed. – Claudio Weiler Jun 23 '22 at 16:17
  • 2
    Instead of doing this over complicated diffs and applies, just use the [patch staging](https://git-scm.com/book/en/v2/Git-Tools-Interactive-Staging), as already commented in main question. To be precise, you just use `git add -p` – kadewu Jun 23 '22 at 17:14
  • Great tip @kadewu, we can always learn something new! – Claudio Weiler Jun 23 '22 at 18:29
2

I would start by doing a

git reset --soft HEAD^

This would take you back in the commit history to the previous commit, just before your big commit, while preserving on disk the changes you made in the last commit.

Next step would be to create a new branch at this commit, to create your two new commits in.

git checkout -b new-branch-name

Since you have changed a lot of files I would then recommend a nice Git GUI to be able to easily pick and choose what to put in which of the commits. With a good enough GUI it is even easy to pick and choose separate sections of files to go in different commits.

Many IDEs have great Git integrations and plugins that can help you with staging different chunks of files instead of whole files.

Some IDEs I use that support this are:

  • VS Code with the GitLens plugin
  • IntelliJ

Some Git GUIs that I use that support this are:

  • SourceTree
  • GitKraken

Use whatever tool you feel comfortable with and do the staging and committing with.

After your first commit, you should run your unit tests without the remaining changes that you want to have in the next commit. Here you can employ the stash command

git stash

This will create a stash with the files that have uncommitted changes. Now your working directory is clean and you can run your tests.

If you missed something you can pop the stash, i.e. the uncommitted changes, back into the the working folder using

git stash pop

Then make additional changes to the first commit with the GUI and redo the commit with the additional changes (i.e. amend) using

git commit --amend

Repeat the testing until done and then the last step would be to create a new commit with the remaining changes and of course also test them.

git stash pop
git add . # Assuming you are in the repo root folder
git commit -m "<good commit message>"

You now have the original commit split up into two commits on your new branch and can push it to the server for review.

cb2
  • 679
  • 9
  • 15