I have several commits that do ineffective changes to a file but some of them are combined with relevant changes to another file. So I would like to just squash the changes to the one file. How can I do that?
Example:
The following should symbolize the commits and the [......]
the content of the file.
This is what I have:
file A: [.....] file B: [......]
file A: [ ] file B: [.... ]
file A: [.....] file B: [... ]
file A: [ ] file B: [... ]
file A: [.....] file B: [.. ]
The diff would be:
file A: [+++++] file B: [....++]
file A: [-----] file B: [...+ ]
file A: [+++++] file B: [... ]
file A: [-----] file B: [..+ ]
file A: [+++++] file B: [++ ]
In this case file A at commits 5, 3 and 1 is the same.
This is what I want: So I would like to squash it to have.
file A: [.....] file B: [......]
file A: [.....] file B: [.... ]
file A: [.....] file B: [... ]
file A: [.....] file B: [.. ]
The diff would be:
file A: [.....] file B: [....++]
file A: [.....] file B: [...+ ]
file A: [.....] file B: [..+ ]
file A: [+++++] file B: [.. ]
Is there any way to do that.
Edit: Maybe I was not very clear in my question. I know how to do interactive rebasing and squash in general. It is more about the fact, that I want to only "squash" the ineffective changes of file A, while I preserve the changes on file B. (Doing this would result in commit 3 doing nothing, and thus it is removed.)
The problem I'm facing with "normal" rebasing would be, if I just squash all commits from 1-5, I would end up with the result I want for file A, but all intermediate changes to file B are lost.
I have added a representation of diff to maybe better depict the situation.
There will be multiple interactive rebases. To sum up, you should edit commit 4
and commit 5
while interactive rebasing. Let me explain:
You already found that squashing commit 2
and commit 3
is the first step. When we just do that, the beginning of the commit history will be like after first interactive rebase:
file A: [.....] file B: [... ]
file A: [.....] file B: [.. ]
Well, let's analyze the scenario. Your file B
changes will be kept, the same as commit 4
and commit 5
. However, we need to get rid of file A
changes. This is where we will get help from edit option in interactive rebase.
While interactive rebasing, select edit option for commit 4
and commit 5
. While editing state for both commits, seperate file A changes from the commit. So a sample history will be look like after second interactive rebase:
1--2--4A--4B--5A--5B
that 4A
only includes changes in file A
at commit 4
. Then final rebase; move 5A
commit next to 4A
commit and squash two commits into commit 2
. And magic, because they are opposite commits, they will be disappeared. And commit history will look like after third interactive rebase:
file A: [.....] file B: [......]
file A: [.....] file B: [.... ]
file A: [.....] file B: [... ]
file A: [.....] file B: [.. ]
as you wanted.