- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
有什么方法可以在分支上以增量方式使用分支过滤器吗?
大致这样说(但这实际上不起作用):
git checkout -b branchA origin/branchA
git branch headBranchA
# inital rewrite
git filter-branch ... -- branchA
git fetch origin
# incremental rewrite
git filter-branch ... -- headBranchA..origin/branchA
git merge origin/branchA
最佳答案
我不确定您真正要实现的目标,因此我在这里要说的是“是的,有点,但可能不是您的想法,无论那是什么,它都可能无法帮助您实现目标”。
重要的是,不仅要了解filter-branch
的功能,而且还要在某种程度上了解它的功能。
背景(使此答案对其他人有用)
git存储库包含一些提交图。这些是通过以下方式找到的:通过外部引用找到了一些起始提交节点(主要是分支和标签名称,还有带注释的标签,在这种情况下,我认为这并不是特别重要),然后使用这些起始节点来查找更多的节点,直到找到所有“可达”节点。
每个提交都有零个或多个“父提交”。大多数普通的提交都有一个父母。合并有两个或多个父母。根提交(例如存储库中的初始提交)没有父级。
分支名称指向一个特定的提交,它指向其父级,依此类推。
B-C-D
/ \
A---E---F <-- master
\
G J <-- branch1
\ /
H-I-K <-- branch2
master
指向提交
F
(这是一个合并提交)。名称
branch1
和
branch2
分别指向commit
J
和
K
。
master
中的“可访问集”为
A B C D E F
,
branch1
的集为
A G H I J
,而
branch2
的集为
A G H I K
。
git rev-parse
和
git rev-list
rev-parse
命令将
any valid git revision specifier转换为提交ID。 (它也有很多我们可以称为“辅助模式”的功能,它们允许将大多数git命令作为shell脚本编写,而
git filter-branch
实际上是一个shell脚本。)
rev-list
命令将修订范围(也在
gitrevisions中)转换为提交ID列表。仅给出一个分支名称,它就会找到该分支可到达的所有修订的集合,因此,在上面的示例提交图中,给出
branch2
,它列出了
A
,
G
,
H
,
I
和
K
的SHA-1值。 (默认情况下按相反的时间顺序列出它们,但是可以告诉他们按“地形顺序”列出它们,这对于
filter-branch
很重要,而不是我打算在这里深入了解细节。)
A..B
语法)或给定诸如
B ^A
的内容,
git rev-list
将其输出修订集限制为
B
可以访问但不可访问的提交。来自
A
。因此,给定
branch2~3..branch2
或等效地称为
branch2 ^branch2~3
,它列出了
H
,
I
和
K
的SHA-1值。这是因为
branch2~3
名称落实
G
,因此将
A
和
G
的提交从可达集中删除。
git filter-branch
git rev-parse
查找要过滤的一个或多个分支的实际头部修订。实际上,它使用了两次:一次获取SHA-1值,一次获取名称。给定例如
headBranchA..origin/branchA
,它需要获取“真实全名”
refs/remotes/origin/branchA
:
git rev-parse --revs-only --symbolic-full-name headBranchA..origin/branchA
refs/remotes/origin/branchA
^refs/heads/headBranchA
^
前缀的结果,以获取“正引用名称”列表;这些都是最终打算重写的内容。
git rev-list
获取要在其上应用过滤器的提交SHA-1的完整列表。这就是
headBranchA..origin/branchA
限制语法出现的地方:该脚本现在知道仅适用于
origin/branchA
可以到达的提交,而不适用于
headBranchA
可以到达的提交。
git filter-branch
实际上就会应用过滤器。这些做出新的 promise 。
filter-branch
脚本更新了“正引用”。
git checkout -b branchA origin/branchA
branchA
上,即
HEAD
包含
ref: refs/heads/branchA
)
git branch headBranchA
HEAD
提交,但不会更改
HEAD
)
# inital rewrite
git filter-branch ... -- branchA
branchA
。除了根提交
branchA
之外,其余的提交都是可以从
o
到达的每个提交,即下面的所有
R
节点(开始提交图组成的图示)。
R-o-o-x-x-x <-- master
\
o-o-o <-- headBranchA, HEAD=branchA, origin/branchA
o
提交,并移动
branchA
指向最后一个新提交:
R-o-o-x-x-x <-- master
| \
| o-o-o <-- headBranchA, origin/branchA
\
*-*-*-*-* <-- HEAD=branchA
origin
拾取新内容:
git fetch origin
n
的提交(我将仅添加一个):
R-o-o-x-x-x <-- master
| \
| o-o-o <-- headBranchA
| \
| n <-- origin/branchA
\
*-*-*-*-* <-- HEAD=branchA
git filter-branch ... -- headBranchA..origin/branchA
origin/branchA
,因此将被移动。
rev-list选择的提交只是标记为
n
的那些,这就是您想要的。这次让我们拼写重写的提交
N
(大写):
R-o-o-x-x-x <-- master
| \
| o-o-o <-- headBranchA
| |\
| | n [semi-abandoned - filter-branch writes refs/original/...]
| \
| N <-- origin/branchA
\
*-*-*-*-* <-- HEAD=branchA
git merge origin/branchA
,这意味着
git merge
提交
N
,这需要找到
*
链与commit
N
...之间的合并基础,这就是
R
的提交。
N
落实到
*
链上。让我们画一下:
R-o-o-x-x-x <-- master
| \
| o-o-o <-- headBranchA
| |\
| | n [semi-abandoned - filter-branch writes refs/original/...]
| \
| N <-- origin/branchA
\
*-*-*-*-*-N'<-- HEAD=branchA
N
,并且也不想移动
origin/branchA
,因为(我假设)您希望以后可以重复
git fetch origin
步骤。因此,让我们“撤消”此操作并尝试其他操作。让我们完全删除
headBranchA
标签,并从此开始:
R-o-o-x-x-x <-- master
| \
| o-o-o <-- origin/branchA
\
*-*-*-*-* <-- HEAD=branchA
origin/branchA
指向的提交添加一个临时标记,然后运行
git fetch origin
,以便获得commit
n
:
R-o-o-x-x-x <-- master
| \ .--------temp
| o-o-o-n <-- origin/branchA
\
*-*-*-*-* <-- HEAD=branchA
n
复制到
branchA
,并在我们对其进行复制的同时,对其进行修改(执行对
git filter-branch
的任何修改)以获得一次提交,我们将只调用
N
:
R-o-o-x-x-x <-- master
| \ .--------temp
| o-o-o-n <-- origin/branchA
\
*-*-*-*-*-N <-- HEAD=branchA
temp
并准备重复该循环。
n
(或几个/很多
n
)然后进行修改?好吧,假设您已经使用了
filter-branch
,最简单的方法是使用
git cherry-pick
复制它们,然后使用
git filter-branch
过滤它们。
cherry-pick
步骤不会遇到树差异问题的情况下才有效,因此这取决于您的过滤器执行的操作:
# all of this to be done while on branchA
git tag temp origin/branchA
git fetch origin # pick up `n` commit(s)
git tag temp2 # mark the point for filtering
git cherry-pick temp..origin/branchA
git filter-branch ... -- temp2..branchA
# remove temporary markers
git tag -d temp temp2
n
提交,给出
n'
提交,然后复制
n'
提交。这些(
n''
)提交将保留在本地(已过滤的)
branchA
上。
n'
提交一旦被复制就不再需要,因此我们将其丢弃。
# lay down temporary marker as before, and fetch
git tag temp origin/branchA
git fetch origin
# now make a new branch, just for filtering
git checkout -b temp2 origin/branchA
git filter-branch ... -- temp..temp2
# the now-altered new branch, temp..temp2, has filtered commits n'
# copy n' commits to n'' commits on branchA
git checkout branchA
git cherry-pick temp..temp2
# and finally, delete the temporary marker and the temporary branch
git tag -d temp
git branch -D temp2 # temp2 requires a force-delete
branchA
中。但是,如果当您查阅
origin
时发现提交已被删除,会发生什么情况?
R-o-o-x-x-x <-- master
| \
| o-o-o <-- origin/branchA
\
*-*-*-*-* <-- HEAD=branchA
git fetch origin
。但是他们所做的是删除最后的
o
提交,并在其末端强制执行。现在我们有:
R-o-o-x-x-x <-- master
| \
| o-o <-- origin/branchA
| `o.......temp
\
*-*-*-*-* <-- HEAD=branchA
branchA
备份为一个修订版本。
git rev-list temp..origin/branchA
的结果在这种特殊情况下将为空(修订后的
origin/branchA
上没有从
temp
无法到达的提交),但是
origin/branchA..temp
不会为空:它将列出一个“已删除”的提交。如果删除了两个提交,它将列出两个提交,依此类推。
origin
的任何人都有可能删除了多个提交并添加了一些其他新的提交(实际上,这正是“上游重新设置”所发生的)。在这种情况下,两个
git rev-list
命令都是非空的:
origin/branchA..temp
将显示删除的内容,
temp..origin/branchA
将显示添加的内容。
origin
的任何人都有可能为您彻底破坏一切。他们能:
branchA
或branchA
指向一个不相关的分支。 关于git - 以增量方式使用过滤器分支的任何方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22014090/
我使用 Git 有一段时间了,但尽管在博客和教程上花了很多时间,但我仍然无法理解某些功能...:) 我正在与其他人合作一个项目,我的老板为此在 bitBucket 上创建了一个存储库。 我在本地克隆了
有时我会遇到以下问题: 在功能分支中添加一些提交。 从上游更新 master。 想要查看功能分支和 master 之间的差异,但是 git diff master 显示了在 master 中添加/删除
我使用的是 Gerrit 2.4.2 版。我有一个分支 master,我创建了一个名为 newbranch 的新分支。然后我将一些更改推送到远程(Gerrit 的)newbranch。在 Gerrit
假设我们有一个远程存储库并在本地克隆它。 我们 checkout master 分支,所以现在我们有本地 master 和一个 Remote remotes/origin/master . 然后我必须
我有一个项目,其中开发分支使用 CocoaPods,但其中一位开发人员决定删除它并改用 Carthage。 feature 分支使用的是 CocoaPods,因为它是在 develop 分支转换之前一
我有一个有问题的 master 分支需要调试。为此,我想插入一堆调试程序(例如,打印变量),查明错误并应用修复程序。稍后,我想将修复 merge 到 master 分支中,但我不想跳过调试更改。 #
我有一个 master 分支,我正在其中 push 我的最新开发。 现在在某个时候,我确实从 master 分支发布并创建了名为 release1 的新分支。 现在我在master分支上做新的开发 与
我正在尝试使我的一些标准工作流程自动化,我发现自己经常做的一件事是将对远程 master 分支的更改 merge 到我自己的本地分支并推送结果。 所以步骤如下: 转为大师 从远程 pull 更改 切换
使用 Gerrit 很容易意外地将开发分支中的不稳定代码 merge 到稳定分支中: $ git checkout develop $ commit $ git push origin HEAD:re
我有一个正在进行的项目,我正在雇用承包商来帮助我处理代码的某些部分。问题是我不想让任何一个承包商看到所有这些。 我可以在 GitHub 上为他们分配私有(private)存储库下的分支吗?这需要命令行
SVN 分支 Branch 选项会给开发者创建出另外一条线路。当有人希望开发进程分开成两条不同的线路时,这个选项会非常有用。我们先假设你已经发布了一个产品的 1.0 版本,你可能想创建一个新的分支,
关闭。这个问题是opinion-based .它目前不接受答案。 想改进这个问题?更新问题,以便 editing this post 提供事实和引用来回答它. 2年前关闭。 Improve this
有没有办法从特定的修订版中创建(svn)分支, 因为我想跳过提交历史中的一些修订(在新分支中)。 例如,我有从 1 到 1590 的修订,我想创建一个新分支并跳过提交(从 1504 到 1574 )和
到目前为止我看到的所有 svn 分支的例子都是这样的 svn cp -m 'Making test branch' svn://svnrepo/hellosite svn://svnrepo/hell
当我尝试使用 Sonar 扫描仪分析我的项目时,扫描失败并显示以下错误消息: Caused by: Branch does not exist on server: develop 显然,这只发生在它
在我的 Mercurial 存储库中,不知何故,有人输入了空白分支名称: 如果我hg id -r 2004,我确实得到空白文本。现在的问题是,这会导致我们的Redmine安装出现问题,因为它无法同步存
我有以下代码片段: srcaddr >= inet_ntoa . fromJust dstaddr >= inet_ntoa . fromJust -- I want to perform actio
在我的项目中,我有用于工作的本地分支和网络驱动器上的分支我在本地一号和网络一号之间做了“绑定(bind)分支”我的想法是使用绑定(bind)选项自动备份每个本地提交。 我在本地分支提交文件后,我在网络
我想创建一个脚本,根据变量的状态使用不同的表和命令执行不同的操作。在 T-SQL 中,我会这样做: DECLARE @whatToDo INT = 1; IF @whatToDo = 1 BEGIN
Write a program that reads input up to # and reports the number of times that the sequence ei occurs
我是一名优秀的程序员,十分优秀!