git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* squash commits deep down in history
@ 2014-10-23 12:34 Henning Moll
  2014-10-23 20:08 ` Johannes Sixt
  2014-11-04 17:25 ` Phil Hord
  0 siblings, 2 replies; 5+ messages in thread
From: Henning Moll @ 2014-10-23 12:34 UTC (permalink / raw)
  To: git

Hi,

i need to squash several commits into a single one in a automated way. I know that there is interactive rebase, which can also be automated using GIT_SEQUENCE_EDITOR. Unfortunately my history is very large and i need to squash deep down in the history several times. So using interactive rebase seems not to be the right tool.

I wonder if i can solve this task using filter-branch? I have a file that list the SHA1s for each squash operation per line. All SHA1s of a line are in chronological order (youngest to oldest), or in other words: the first SHA1 is the child of the second, and so on.

| ab4423e 3432343 3234252
| 2324342 5232343
| ...

Lets say there are N lines in that file. Each line means: squash all SHA1s of this line into the first (or last) SHA1 of this line.
Performing this task with rebase would require N rewritings of the history. So e.g. HEAD (but many others too) would be rewritten N times even if it is not directly part of a line. My thinking is, that a filter-branch can do this in a single rewrite and therefore would be much more performant.

How can i solve this? Any ideas?

Best regards
Henning

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: squash commits deep down in history
  2014-10-23 12:34 squash commits deep down in history Henning Moll
@ 2014-10-23 20:08 ` Johannes Sixt
  2014-10-23 22:20   ` Henning Moll
  2014-10-24 11:43   ` Jakub Narębski
  2014-11-04 17:25 ` Phil Hord
  1 sibling, 2 replies; 5+ messages in thread
From: Johannes Sixt @ 2014-10-23 20:08 UTC (permalink / raw)
  To: Henning Moll, git

Am 23.10.2014 um 14:34 schrieb Henning Moll:
> i need to squash several commits into a single one in a automated
> way. I know that there is interactive rebase, which can also be
> automated using GIT_SEQUENCE_EDITOR. Unfortunately my history is very
> large and i need to squash deep down in the history several times. So
> using interactive rebase seems not to be the right tool.
> 
> I wonder if i can solve this task using filter-branch? I have a file
> that list the SHA1s for each squash operation per line. All SHA1s of
> a line are in chronological order (youngest to oldest), or in other
> words: the first SHA1 is the child of the second, and so on.

Use git-replace do construct a squashed commit that replaces the last
child in each run such that its parent points to the parent of the first
in the run. Then use a git-filterbranch without filters to burn the
parenthood into the history.

-- Hannes

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: squash commits deep down in history
  2014-10-23 20:08 ` Johannes Sixt
@ 2014-10-23 22:20   ` Henning Moll
  2014-10-24 11:43   ` Jakub Narębski
  1 sibling, 0 replies; 5+ messages in thread
From: Henning Moll @ 2014-10-23 22:20 UTC (permalink / raw)
  To: git; +Cc: Johannes Sixt

Am 23.10.2014 um 22:08 schrieb Johannes Sixt:
> Use git-replace do construct a squashed commit that replaces the last 
> child in each run such that its parent points to the parent of the 
> first in the run. Then use a git-filterbranch without filters to burn 
> the parenthood into the history. -- Hannes 
Wow, cool. Thanks a lot for the hint.

I managed to do the following: Suppose i have the following history


A - B - C - D   <-master

and i want to squash B and C together. First i create a temporary branch 
on A and switch to it. Then i cherry-pick B and C without commit. So all 
the changes are merged into the index. Then i commit a single commit 
"M". The history now looks like

   M             <-temp
  /
A - B - C - D   <-master

Using

$ git replace C M

leads to

    temp
         |
         v

A -     M - D   <-master

As far as i understand, such a repalce is something like a "symbolic 
link". Is that right?

This is interesting: Before filter-branch, the deletion of the replace 
would lead to the initial situation (ABCD). After filter-branch, the 
history is (AM'D'). The replace still exists but is now something like a 
"dead link". I may come to life again after "git resetting" to somewhere 
before filter-branch. Even "before" creating the replace (the replace 
ref itself is not part of the history). Even if you gor before creation 
of M: The link still works as long as M is not garbage collected. I was 
very irritated after resetting to where i commited D, and still seeing 
A-M-D.

Somehow logical, somehow crazy! I am still a git learner ;-)

Two questions remain for me:

1. Is there a more elegant way to build M?
2. Having a replace "in place" before filter-branch: Is there a way to 
find out what the replace is hiding? A simple "git log C" produces 
"M-A". How to get "C-B-A"?

Best regards
Henning

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: squash commits deep down in history
  2014-10-23 20:08 ` Johannes Sixt
  2014-10-23 22:20   ` Henning Moll
@ 2014-10-24 11:43   ` Jakub Narębski
  1 sibling, 0 replies; 5+ messages in thread
From: Jakub Narębski @ 2014-10-24 11:43 UTC (permalink / raw)
  To: Johannes Sixt, Henning Moll, git

W dniu 2014-10-23 22:08, Johannes Sixt pisze:
> Am 23.10.2014 um 14:34 schrieb Henning Moll:

>> i need to squash several commits into a single one in a automated
>> way. I know that there is interactive rebase, which can also be
>> automated using GIT_SEQUENCE_EDITOR. Unfortunately my history is very
>> large and i need to squash deep down in the history several times. So
>> using interactive rebase seems not to be the right tool.
>>
>> I wonder if i can solve this task using filter-branch? I have a file
>> that list the SHA1s for each squash operation per line. All SHA1s of
>> a line are in chronological order (youngest to oldest), or in other
>> words: the first SHA1 is the child of the second, and so on.
>
> Use git-replace do construct a squashed commit that replaces the last
> child in each run such that its parent points to the parent of the first
> in the run. Then use a git-filter-branch without filters to burn the
> parenthood into the history.

Using grafts (which are only about parentage, and are purely local) with 
filter-less git-filter-branch might be easier than git-replace.

If you have the following history:

     ... <--- O <--- A <--- B <--- C <--- ...

and you want to squash A, B, C into

     ... <--- O <----------------- C <--- ...

simply add the following to .git/info/grafts

    <sha-1 of C> <sha-1 of O>

for example with

    echo "$(git rev-parse C) $(git rev-parse C^^^)" >>.git/info/grafts

Check if the history is correct e.g. with "git log --graph --oneline",
then use filter-branch.

BTW. do you know if it is possible to run filter-branch without 
replacing replaces?


Just for completeness, yet another way to do scripted history rewriting 
is to use git-fast-export + some editing script (e.g. reposurgeon[1]) + 
git-fast-import.

[1]: http://www.catb.org/esr/reposurgeon/

-- 
Jakub Narębski

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: squash commits deep down in history
  2014-10-23 12:34 squash commits deep down in history Henning Moll
  2014-10-23 20:08 ` Johannes Sixt
@ 2014-11-04 17:25 ` Phil Hord
  1 sibling, 0 replies; 5+ messages in thread
From: Phil Hord @ 2014-11-04 17:25 UTC (permalink / raw)
  To: Henning Moll; +Cc: git@vger.kernel.org, Johannes Sixt, Jakub Narębski

On Thu, Oct 23, 2014 at 8:34 AM, Henning Moll <newsScott@gmx.de> wrote:
> Hi,
>
> i need to squash several commits into a single one in a automated way. I know that there is interactive rebase, which can also be automated using GIT_SEQUENCE_EDITOR. Unfortunately my history is very large and i need to squash deep down in the history several times. So using interactive rebase seems not to be the right tool.
>
> I wonder if i can solve this task using filter-branch? I have a file that list the SHA1s for each squash operation per line. All SHA1s of a line are in chronological order (youngest to oldest), or in other words: the first SHA1 is the child of the second, and so on.
>
> | ab4423e 3432343 3234252
> | 2324342 5232343
> | ...
>
> Lets say there are N lines in that file. Each line means: squash all SHA1s of this line into the first (or last) SHA1 of this line.

I've often felt there should be some simple commands to do these kinds
of edits.  For example, it is easy to amend HEAD, but an
order-of-magnitude more difficult to amend HEAD^.   I imagine commands
like this:

   git rebase --reword HEAD^
   git rebase --edit some-old-commit
   git rebase --squash ab4423e 3432343 3234252

But each time I think of implementing one of these I am daunted by the
many exceptional cases.


> Performing this task with rebase would require N rewritings of the history. So e.g. HEAD (but many others too) would be rewritten N times even if it is not directly part of a line. My thinking is, that a filter-branch can do this in a single rewrite and therefore would be much more performant.
>
> How can i solve this? Any ideas?

I know you solved this already with filter-branch, but that seems like
a complicated solution to me.  I think the --interactive rebase would
have been useful for you.  You should keep in mind that you do not
need to repeat the command multiple times for your multiple squashes.
For example, if your to-do list looks like this simple example:

pick 0000000
pick ab4423e
pick 3432343
pick 3234252
pick 0000001
pick 0000002
pick 2324342
pick 5232343
pick 0000003

I think you could get the desired effect by changing it to this:

pick 0000000
pick ab4423e
squash 3432343
squash 3234252
pick 0000001
pick 0000002
pick 2324342
squash 5232343
pick 0000003

And then running that all in one interactive rebase.  Does that make sense?

Phil

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2014-11-04 17:25 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-10-23 12:34 squash commits deep down in history Henning Moll
2014-10-23 20:08 ` Johannes Sixt
2014-10-23 22:20   ` Henning Moll
2014-10-24 11:43   ` Jakub Narębski
2014-11-04 17:25 ` Phil Hord

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).