Git 2.18(2018年第二季度)将通过添加一个新选项大大改进——preserve-merge选项。
“git rebase”学会了“-rebase-merges”移植整个
在其他地方提交图的拓扑。
(注:Git 2.22, 2019年第二季度,实际上已弃用-保存-合并,而Git 2.25, 2020年第一季度,停止在“Git rebase -help”输出中宣传它)
参见Johannes Schindelin (dscho)的commit 25cff9f, commit 7543f6f, commit 1131ec9, commit 7ccdf65, commit 537e7d6, commit a9be29c, commit 8f6aed7, commit 1644c73, commit d1e8b01, commit 4c68e7d, commit 9055e40, commit cb5206e, commit a01c2a5, commit 2f6b1d1, commit bf5c057(2018年4月25日)。
参见Stefan Beller (stefanbeller)提交f431d73(2018年4月25日)。
参见Phillip Wood提交2429335(2018年4月25日)。
(由Junio C Hamano - gitster -在commit 2c18e6a中合并,2018年5月23日)
Pull: accept——rebase-merges来重新创建分支拓扑
类似于保存模式,只需传递——preserve-merges
选项设置为rebase命令时,合并模式将简单地传递
——rebase-merges选项。
这将允许用户方便地更改非平凡提交的基准
在拉出新提交时的拓扑,而不会将它们平铺。
Git rebase手册页现在有一个完整的部分专门用于用合并来重基历史。
精华:
There are legitimate reasons why a developer may want to
recreate merge commits: to keep the branch structure (or "commit
topology") when working on multiple, inter-related branches.
In the following example, the developer works on a topic branch that
refactors the way buttons are defined, and on another topic branch
that uses that refactoring to implement a "Report a bug" button.
The output of git log --graph --format=%s -5 may look like this:
* Merge branch 'report-a-bug'
|\
| * Add the feedback button
* | Merge branch 'refactor-button'
|\ \
| |/
| * Use the Button class for all buttons
| * Extract a generic Button class from the DownloadButton one
The developer might want to rebase those commits to a newer master
while keeping the branch topology, for example when the first topic
branch is expected to be integrated into master much earlier than the
second one, say, to resolve merge conflicts with changes to the
DownloadButton class that made it into master.
This rebase can be performed using the --rebase-merges option.
请看commit 1644c73的一个小例子:
rebase-helper——make-script:引入一个标志来rebase merge
音序器刚刚学会了重新创建分支的新命令
结构(在精神上类似于——preserve-merges,但带有
更少损坏的设计)。
让我们允许rebase——helper生成使用的待办事项列表
这些命令由新的——rebase- merged选项触发。
对于这样的提交拓扑(HEAD指向C):
- a - b - c(头)
\ /
D
生成的todo列表看起来像这样:
# D分支
pick 0123 A
标签分叉点
pick 1234选择D
标签维
重置分叉点
pick 2345 B
C; C
保留-合并有什么区别?
Commit 8f6aed7解释道:
Once upon a time, this here developer thought: wouldn't it be nice if,
say, Git for Windows' patches on top of core Git could be represented as
a thicket of branches, and be rebased on top of core Git in order to
maintain a cherry-pick'able set of patch series?
The original attempt to answer this was: git rebase --preserve-merges.
However, that experiment was never intended as an interactive option,
and it only piggy-backed on git rebase --interactive because that
command's implementation looked already very, very familiar: it was
designed by the same person who designed --preserve-merges: yours truly.
And by "yours truly", the author refers to himself: Johannes Schindelin (dscho), who is the main reason (with a few other heroes -- Hannes, Steffen, Sebastian, ...) that we have Git For Windows (even though back in the day -- 2009 -- that was not easy).
He is working at Microsoft since Sept. 2015, which makes sense considering Microsoft now heavily uses Git and needs his services.
That trend started in 2013 actually, with TFS. Since then, Microsoft manages the largest Git repository on the planet! And, since Oct. 2018, Microsoft acquired GitHub.
你可以看到Johannes在2018年4月Git Merge 2018的视频中发言。
过了一段时间,其他开发人员(我在看着你,Andreas!)
;-))决定允许-preserve-merges到是一个好主意
与——interactive(注意!)和Git维护器结合使用
(嗯,是指Junio不在期间的临时Git维护者)
同意,这就是——保存——设计的魅力所在
开始迅速而平淡地崩溃。
乔纳森正在谈论来自Suse的Andreas Schwab。
你可以看到他们在2012年的一些讨论。
The reason? In --preserve-merges mode, the parents of a merge commit (or
for that matter, of any commit) were not stated explicitly, but were
implied by the commit name passed to the pick command.
This made it impossible, for example, to reorder commits.
Not to mention to move commits between branches or, deity forbid, to split topic branches into two.
Alas, these shortcomings also prevented that mode (whose original
purpose was to serve Git for Windows' needs, with the additional hope
that it may be useful to others, too) from serving Git for Windows'
needs.
Five years later, when it became really untenable to have one unwieldy,
big hodge-podge patch series of partly related, partly unrelated patches
in Git for Windows that was rebased onto core Git's tags from time to
time (earning the undeserved wrath of the developer of the ill-fated
git-remote-hg series that first obsoleted Git for Windows' competing
approach, only to be abandoned without maintainer later) was really
untenable, the "Git garden shears" were born: a script,
piggy-backing on top of the interactive rebase, that would first
determine the branch topology of the patches to be rebased, create a
pseudo todo list for further editing, transform the result into a real
todo list (making heavy use of the exec command to "implement" the
missing todo list commands) and finally recreate the patch series on
top of the new base commit.
(Git花园剪切脚本在提交9055e40中被引用)
That was in 2013.
And it took about three weeks to come up with the design and implement it as an out-of-tree script. Needless to say, the implementation needed quite a few years to stabilize, all the while the design itself proved itself sound.
With this patch, the goodness of the Git garden shears comes to git rebase -i itself.
Passing the --rebase-merges option will generate
a todo list that can be understood readily, and where it is obvious
how to reorder commits.
New branches can be introduced by inserting label commands and calling merge <label>.
And once this mode will have become stable and universally accepted, we can deprecate the design mistake that was --preserve-merges.
Git 2.19(2018年第三季度)改进了新的——rebase-merge选项,使其与——exec一起工作。
"git rebase- rebase-merges"的"——exec"选项放置了exec
命令在错误的地方,这已被纠正。
参见Johannes Schindelin (dscho)的commit 1ace63b(2018年8月09日)和commit f0880f7(2018年8月06日)。
(由Junio C Hamano - gitster -在commit 750eb11, 2018年8月20日合并)
Rebase——exec:让它与——Rebase -merges一起工作
The idea of --exec is to append an exec call after each pick.
Since the introduction of fixup!/squash! commits, this idea was extended
to apply to "pick, possibly followed by a fixup/squash chain", i.e. an
exec would not be inserted between a pick and any of its corresponding
fixup or squash lines.
The current implementation uses a dirty trick to achieve that: it
assumes that there are only pick/fixup/squash commands, and then
inserts the exec lines before any pick but the first, and appends
a final one.
With the todo lists generated by git rebase --rebase-merges, this
simple implementation shows its problems: it produces the exact wrong
thing when there are label, reset and merge commands.
Let's change the implementation to do exactly what we want: look for
pick lines, skip any fixup/squash chains, and then insert the exec
line. Lather, rinse, repeat.
Note: we take pains to insert before comment lines whenever possible,
as empty commits are represented by commented-out pick lines (and we
want to insert a preceding pick's exec line before such a line, not
afterward).
While at it, also add exec lines after merge commands, because they
are similar in spirit to pick commands: they add new commits.
Git 2.22 (Q2 2019)修复了使用refs/重写/层次结构来存储rebase中间状态的问题,这固有地使层次结构每
worktree。
参见nguyfrecn Thái ngibmc Duy (pclouds)的commit b9317d5, commit 90d31ff, commit 09e6564 (07 Mar 2019)。
(由Junio C Hamano - gitster -在commit 917f2cd中合并,2019年4月9日)
确保refs/重写/是每个工作树
A9be29c (sequencer:使label命令生成的ref
worktree-local, 2018-04-25, Git 2.19)按每个工作树添加引用/重写/
参考空间。
不幸的是(我的错)有几个地方
需要更新,以确保它真的是每个工作树。
更新Add_per_worktree_entries_to_dir()以确保引用列表
查看每个工作树的引用/重写/而不是每个repo。
Common_list[]被更新,以便git_path()返回正确的
的位置。这包括"rev-parse——git-path"。
这一团糟是我造成的。
我开始尝试通过引入refs/工作树来修复它,其中所有的引用都将是每个工作树,没有特殊的处理。
不幸的是,refs/重写出现在refs/工作树之前,所以这是我们所能做的。
在Git 2.24(2019年第四季度)中,“Git rebase- rebase-merges”学会了驱动不同的合并策略,并将特定于策略的选项传递给它们。
参见以利亚·纽伦(Newren)提交476998d(2019年9月04日)。
参见Johannes Schindelin (dscho)的commit e1fac53, commit a63f990, commit 5dcdd74, commit e145d99, commit 4e6023b, commit f67336d, commit a9c7107, commit b8c6f24, commit d51b771, commit c248d32, commit 8c1e240, commit 5efed0e, commit 68b54f6, commit 2e7bac, commit 6180b20, commit d5b581f(2019年7月31日)。
(由Junio C Hamano - gitster -在提交917a319中合并,2019年9月18日)
在Git 2.25 (Q1 2020)中,用来区分工作树本地引用和存储库全局引用的逻辑是固定的,以方便保存-合并。
参见commit f45f88b, commit c72fc40, commit 8a64881, commit 7cb8c92, commit e536b1f(2019年10月21日)by SZEDER Gábor (SZEDER)。
(由Junio C Hamano合并- gitster -在commit db806d7, 2019年11月10日)
Path.c:不调用trie_find()中没有值的match函数
署名:SZEDER Gábor
'logs/refs' is not a working tree-specific path, but since commit b9317d55a3 (Make sure refs/rewritten/ is per-worktree, 2019-03-07, v2.22.0-rc0) 'git rev-parse --git-path' has been returning a bogus path if a trailing '/' is present:
$ git -C WT/ rev-parse --git-path logs/refs --git-path logs/refs/
/home/szeder/src/git/.git/logs/refs
/home/szeder/src/git/.git/worktrees/WT/logs/refs/
We use a trie data structure to efficiently decide whether a path belongs to the common dir or is working tree-specific.
As it happens b9317d55a3 triggered a bug that is as old as the trie implementation itself, added in 4e09cf2acf ("path: optimize common dir checking", 2015-08-31, Git v2.7.0-rc0 -- merge listed in batch #2).
According to the comment describing trie_find(), it should only call the given match function 'fn' for a "/-or-\0-terminated prefix of the key for which the trie contains a value".
This is not true: there are three places where trie_find() calls the match function, but one of them is missing the check for value's existence.
b9317d55a3 added two new keys to the trie:
'logs/refs/rewritten', and
'logs/refs/worktree', next to the already existing 'logs/refs/bisect'.
This resulted in a trie node with the path 'logs/refs/', which didn't exist before, and which doesn't have a value attached.
A query for 'logs/refs/' finds this node and then hits that one callsite of the match function which doesn't check for the value's existence, and thus invokes the match function with NULL as value.
When the match function check_common() is invoked with a NULL value, it returns 0, which indicates that the queried path doesn't belong to the common directory, ultimately resulting the bogus path shown above.
Add the missing condition to trie_find() so it will never invoke the match function with a non-existing value.
check_common() will then no longer have to check that it got a non-NULL value, so remove that condition.
I believe that there are no other paths that could cause similar bogus output.
AFAICT the only other key resulting in the match function being called with a NULL value is 'co' (because of the keys 'common' and 'config').
However, as they are not in a directory that belongs to the common directory the resulting working tree-specific path is expected.
确保使用Git 2.34 (Q4 2021),以避免内存泄漏。
参见Ævar Arnfjörð Bjarmason (avar)的commit 6e65854, commit 0c52cf8(2021年10月13日)和commit e5a917f(2021年10月07日)。
参见Junio C Hamano (gitster)提交的commit 9d05b45(2021年10月07日)。
(由Junio C Hamano—gitster—在commit bfa646c中合并,2021年10月25日)
Sequencer:修复do_reset()中的内存泄漏
署名:Ævar Arnfjörð Bjarmason
修复9055e40中引入的内存泄漏(“sequencer:引入新的命令来重置修订版”,2018-04-25,Git v2.18.0-rc0—merge列在批处理#6中),它调用setup_unpack_trees_porcelain()而没有相应调用clear_unpack_trees_porcelain()。