在filter-branch移动根目录之后重复提交 [英] Duplicate commits after filter-branch to move root directory

查看:94
本文介绍了在filter-branch移动根目录之后重复提交的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的存储库设置出现问题:我在错误的目录中初始化了我的存储库并开始使用它。我已经创建了一些分支并再次合并它们。我想保留这段历史。



现在如何:

  wrongRootProjectDir / 
|
+ - 。git
|
+ -realProjectDir
|
+ - <项目文件>

它应该是这样的:

  realProjectDir 
|
+ - 。git
|
+ - <项目文件>

所以基本上我想把所有的目录都移到一个目录。 wrongRootProjectDir 也只包含 .git 文件和 realProjectDir 目录。



我在SO 我怎么能移动一个目录在Git仓库所有提交?可能有一种方法。我运行了一个 git clone oldrepo newrepo 来获得一个备份仓库,并运行

  git filter-branch --subdirectory-filter realProjectDir  -  --all 

它似乎工作,但是我从旧的存储库中丢失了我的合并和分支结构。过滤回购有正确的路径,但缺乏合并提交。另外旧的提交还在,所以回购看起来像这样:

 (提交A)
|
(Commit B)
|
(Commit C)
|
(Commit A')
|
(Commit B')
|
(Commit C')

其中A'是新的提交。我的多个分支有问题,并使用 filter-branches ?所以现在我每次提交两次,一次使用了错误的旧路径,一次使用了新路径。


$ b

总结

有没有一种方法可以向上移动一个完整的目录树并保持所有分支和合并而不产生双提交?



更新
我仍​​然无法保留我的合并提交和正确的分支布局。所有东西都被拼凑成一连串的提交。


更新

树之前:





以及使用 gitk 运行过滤分支之后:



我运行这个命令时工作目录是干净的。为了测试我使用简单的 cp -r 复制整个目录树到另一个目录并在那里测试它。 filter-branch命令在这种意义上起作用,即它移动子目录,但它仍然使历史变平坦。就我所见,我没有做过任何太复杂的事情,只是普通的分支和合并内容。



更新



我之前的状态显示错误的图片。我尝试转换非重写的存储库。

解决方案

filter-branch 与子目录过滤器正是完成此工作的工具。这是它的全部目的。如果你遇到了问题,那是因为你做错了,而你没有告诉我们。 filter-branch 不会压扁历史记录。您可能正在查看 gitk --all 并且看到重写的历史记录和旧的历史记录(它将被标记为 original / refs / heads /...) - 在这种情况下,这两个历史没有连接。你也可以在分支之前做一些事情。当你再次尝试时,你是否在一个新的克隆中做,从你想要的确切的原始历史开始?

下面是关于最简单可能的例子,证明这个完全按照它的样子工作:

  git init 
mkdir subdir
touch x subdir / a subdir / b subdir / c
git add subdir / a
git commit -m'a'
git add subdir / b
git commit -m'b'
git checkout - b foo HEAD ^
git add subdir / c
git commit -m'c'
git checkout master
git merge foo
git add x
git commit -m'x'
git filter-branch --subdirectory-filter subdir - --all
#现在检查eg与gitk --all

原始参考文件保留在refs / original / refs / ...所以如果你搞砸了,你可以回到他们身边。如果你检查结果,并确定一切都很好,那么你可以删除它们。在这个manpage中给出的方法是这样的:

  git for-each-ref --format =%(refname) refs / original / | xargs -n 1 git update-ref -d 

虽然在实践中你也可以做 rm -rf .git / refs / original


I am having a problem with my repository setup: I initialized my repository in the wrong directory and started using it. I already made some branches and merged them again. I would like to keep that history.

How it is now:

wrongRootProjectDir/
|
+-.git
|
+-realProjectDir
   |
   +-<Project files>

How it should look like:

realProjectDir
|
+-.git
|
+-<Project files>

So basically I would like to shift everything one directory up. wrongRootProjectDir also contains only the .git file and the realProjectDir directory.

I found some hints at SO How can I move a directory in a Git repo for all commits? that there could be a way. I run a git clone oldrepo newrepo to get a backup repo and ran

git filter-branch --subdirectory-filter realProjectDir -- --all

on the new repo. It seemed to work, however I have lost my merge and branch structure from the old repository. The filtered repo has the correct paths but is lacking the merge commits. Additionally the old commits are still around, so that the repo looks like this:

(Commit A)
|
(Commit B)
|
(Commit C)
|
(Commit A')
|
(Commit B')
|
(Commit C')

Where A' are the new commits. Is there a problem with my multiple branches and using filter-branches ? So right now I have each commit twice, once with the wrong old path and once with the new one.

Summary

Is there a way of moving a complete directory tree one layer upwards and keeping all branches and merges without generating double commits?

Update I still cannot manage to keep my merge commits and the right branch layout. Everything is flattened into a chain of commits.

Update

Added the history tree before:

and after running filter-branch using gitk:

The working directory is clean when I run this command. To test things I copied the whole directory tree using simple cp -r to another directory and tested it there. The filter-branch command works in that sense that it moves the subdirectory, but it still flattens the history. As far as I can see it, I have not done anything too complicated, just the normal branching and merging stuff.

Update

I showed the wrong picture for the before state. I tried to transform a non-rewritten repository.

解决方案

filter-branch with a subdirectory filter is exactly the tool to do this. This is its entire purpose. If you're having problems, it's because you're doing something wrong that you haven't told us. filter-branch doesn't flatten history. It's possible that you're looking at gitk --all and seeing both the rewritten history and the old history (it'll be marked with original/refs/heads/...) - in that case, note that the two histories aren't connected. It's also possible that you did something to mess things up before the filter-branch. When you're trying again, are you doing it in a fresh clone, starting out from the exact original history you want?

Here's about the simplest possible example demonstrating that this works exactly as it should:

git init
mkdir subdir
touch x subdir/a subdir/b subdir/c
git add subdir/a
git commit -m 'a'
git add subdir/b
git commit -m 'b'
git checkout -b foo HEAD^
git add subdir/c
git commit -m 'c'
git checkout master
git merge foo
git add x
git commit -m 'x'
git filter-branch --subdirectory-filter subdir -- --all
# now inspect e.g. with gitk --all

The original refs are kept around in refs/original/refs/... so that if you screwed up, you can get back to them. If you inspect the results, and decide everything is good, then you can remove them. The method given in the manpage for that is this:

git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d

though in practice you can also just do rm -rf .git/refs/original.

这篇关于在filter-branch移动根目录之后重复提交的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆