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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxx> wrote:
> Hi
>
> On Thu, Mar 8, 2012 at 3:30 PM, Junio C Hamano <gitster@xxxxxxxxx> wrote:
>> Anatol Pomozov <anatol.pomozov@xxxxxxxxx> 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.
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]