如何更改 git 历史记录中的文件路径?

发布于 2024-09-05 23:28:10 字数 413 浏览 5 评论 0 原文

这是我所拥有的 - 我的代码的 git 存储库:

projects
       |-proj1 (no git repo here yet)
             |-subproj1 <- current git repo here

这是我想要的 - 一个 git 存储库,它现在正在跟踪使用我的代码的新项目:

projects
       |-proj1 <-git repo moved to here, but still tracking files in subproj1
             |-subproj1 (no git repo here)

我想保持历史记录完整,因此新存储库将是指比原始文件深一级的文件。最无痛的方法是什么?

Here is what I have - a git repo of my code:

projects
       |-proj1 (no git repo here yet)
             |-subproj1 <- current git repo here

Here is what I want - a git repo which is now tracking a new project that uses my code:

projects
       |-proj1 <-git repo moved to here, but still tracking files in subproj1
             |-subproj1 (no git repo here)

I'd like to keep the history intact and therefore the new repository will be referring to files that are one level deeper than the original. What is the most pain free way to do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

一个人的旅程 2024-09-12 23:28:10

可以使用 git filter-branch 命令来重写历史记录。事实上,将目录树移动到子目录中是 git filter-branch 联机帮助页:

git filter-branch --index-filter '
  git ls-files -s |
  sed "s-\t\"*-&subproj1/-" |
  GIT_INDEX_FILE=$GIT_INDEX_FILE.new git update-index --index-info &&
  mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE
' HEAD

Rewriting history can be done with the git filter-branch command. In fact, moving a directory tree into a subdirectory is one of the cut&paste-ready examples given in the git filter-branch manpage:

git filter-branch --index-filter '
  git ls-files -s |
  sed "s-\t\"*-&subproj1/-" |
  GIT_INDEX_FILE=$GIT_INDEX_FILE.new git update-index --index-info &&
  mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE
' HEAD
吾性傲以野 2024-09-12 23:28:10

Git 并不擅长跟踪文件的移动,因此如果您想保留文件历史记录,则必须确保旧存储库始终将其文件放在您现在需要的子目录中

git-filter-branch 工作得足够好,但是 git-filter-repo,它允许您以更简单的方式追溯移动文件(以及您可以使用 git-filter-branch 执行的其他操作)。

复制自我自己的答案

export SUBTREE_PREFIX="subproj1"

git remote add -f "${SUBTREE_PREFIX:?}-remote" https://my-git-repo.invalid/subproj1.git

git checkout "${SUBTREE_PREFIX:?}-remote"/master -b "${SUBTREE_PREFIX:?}-master"

# --force is to skip the "freshly cloned repo" check.
# All the refs we'll be operating on are fresh, even if the repo isn't

# Remove --dry-run once you've checked .git/filter-repo/fast-export.filtered
# to be sure that everything is correct.
git filter-repo --refs "${SUBTREE_PREFIX:?}-master" --to-subdirectory-filter "${SUBTREE_PREFIX:?}" --force --dry-run

git checkout master
git merge "${SUBTREE_PREFIX:?}-master" --allow-unrelated-histories

# Repeat for however many repos you need to add

另请参阅如何合并两个 Git 存储库?

Git isn't exactly good at tracking files getting moved around, so if you want to preserve file history, you're going to have to make it so the old repository always had its files in the sub-directory you now need it to be in.

git-filter-branch works decently enough, but is no longer recommended. The man page now points to git-filter-repo, which lets you retroactively move files around (among other things you can do with git-filter-branch) in a much simpler way.

Copied from my own answer here:

export SUBTREE_PREFIX="subproj1"

git remote add -f "${SUBTREE_PREFIX:?}-remote" https://my-git-repo.invalid/subproj1.git

git checkout "${SUBTREE_PREFIX:?}-remote"/master -b "${SUBTREE_PREFIX:?}-master"

# --force is to skip the "freshly cloned repo" check.
# All the refs we'll be operating on are fresh, even if the repo isn't

# Remove --dry-run once you've checked .git/filter-repo/fast-export.filtered
# to be sure that everything is correct.
git filter-repo --refs "${SUBTREE_PREFIX:?}-master" --to-subdirectory-filter "${SUBTREE_PREFIX:?}" --force --dry-run

git checkout master
git merge "${SUBTREE_PREFIX:?}-master" --allow-unrelated-histories

# Repeat for however many repos you need to add

See also How do you merge two Git repositories?

屋檐 2024-09-12 23:28:10

只需在存储库中创建您想要的目录结构 - 即将所有文件和文件夹移动到“subproj1”文件夹。

然后暂存所有添加和删除的文件,git 会发现它们实际上是重命名的:

git add .
git add -u .
git commit -m "Moved to a subfolder"

Just create the directory structure you want inside the repo - i.e. move all files and folders to "subproj1" folder.

Then stage all added and deleted files and git will work out that they are in fact renames:

git add .
git add -u .
git commit -m "Moved to a subfolder"
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文