git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: Removing useless merge commit with "filter-branch"

From
Anatol Pomozov <anatol.pomozov@gmail.com>
Date
Mar 29, 2012, 18:26 UTC
Message-ID
<CAOMFOmWrG9WGZCF6j3P=Somo1DDxoB=ALCiYYbjO__8=uxYokg@mail.gmail.com>
In-Reply-To
<CAOMFOmUT+2q7jC9Z1=zFJdBi_KAg=A66yHJNF2LRvjfQcgbdFw@mail.gmail.com>
Hi,

I solved my issue by using "git filter-branch --parent-filter". The idea is to visit all commits and remove all "dependent" parents. To find independent parents I used "git show-branch --independent PARENT_1..PARENT_N" command. In my case (we have a lot of short-term development branches) this converted ~80% of all merges to "empty non-merge commits" and later "git filter-branch --prune-empty" removed them. This made history of my project much more simpler and linear.

I think such functionality should be available in git and enabled when "--prune-empty" flag is used. So "--prune-empty" removes not only simple commits but also empty useless merge commits. Or maybe add a --prune-empty-merges flag?

Anyway here is the script that I use, future readers might find it useful:

$ git filter-branch -f --prune-empty --parent-filter PATH_TO/rewrite_parent.rb master $ cat rewrite_parent.rb #!/usr/bin/ruby old_parents = gets.chomp.gsub('-p ', ' ')

if old_parents.empty? then
  new_parents = []
else
  new_parents = `git show-branch --independent #{old_parents}`.split
end
puts new_parents.map{|p| '-p ' + p}.join(' ')
Most likely the script can be rewritten as one-line shell script.

On Tue, Mar 13, 2012 at 3:27 PM, Anatol Pomozov <anatol.pomozov@gmail.com> wrote:

Show 68 quoted lines
> Hi
>
> On Thu, Mar 8, 2012 at 3:30 PM, Junio C Hamano <gitster@pobox.com> wrote:
>> Anatol Pomozov <anatol.pomozov@gmail.com> writes:
>>
>>> |
>>> o      - merge commit that previously merged feature X
>>> |\
>>> | \
>>> |  \
>>> o  |   - real commit
>>> |   |
>>> |  /
>>> |/
>>> |
>>
>> It is unclear how many commits are drawn in the above picture and
>> what "feature X" is about in the above picture.  Care to redraw the
>> commit DAG to explain what you are trying to do a bit better?
>>
>> The way I read it is that you start from a history like this (note
>> that when we draw an ascii art history we often write it sideways,
>> time flows from left to right):
>>
>>    ---A-----B-----M---
>>        \         /
>>         C-------D
>>
>> where a side branch to implement "feature X" that has C and D forked
>> at A, and it was merged at M after somebody else committed B on the
>> mainline.  When you filtered out some parts of the tree, it turns
>> out that C and D are totally unintereseting because their changes
>> touch parts outside of your interest, i.e. the history is:
>>
>>    ---A-----B-----M---
>>        \         /
>>         o-------o
>>
>> where 'o' are now no-op.
>>
>> Is that what you are talking about?
>
> Yes, in fact --prune-empty flag removes empty commits so the history looks like
>
> -----A-------B-------M--------
>       \               /
>        --------------
>
>
> So M is a merge that has 2 parents A and B. I would like to remove
> this merge M and leave the history as
>
> -----A-----B-----
>
> as only these commits have changes in my library that I am trying to extract.
>
> I think some trickery with "git filter-branch --parent-filter" should help here.
>
> First one runs filter-branch with --parent-filter and removes useless
> parents from merges (in this example with will be parent A---M), this
> converts such merges to regular empty commits
>
> then run filter-branch one more time with --prune-empty - it removes
> empty commits.
>>
>> I think "log --simplify-merges A..M -- path" may already has logic
>> that deals with this, so it may help if you study what it does and
>> how it does what it does.
Previous: Anatol Pomozov
Message 4 of 4 in “Removing useless merge commit with "filter-branch"”
  1. Anatol PomozovMar 8, 2012
  2. Junio C HamanoMar 8, 2012
  3. Anatol PomozovMar 13, 2012
  4. Anatol PomozovMar 29, 2012

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.