多仓库目录结构调整迁移:Git命令能否保留历史实现?
Absolutely! You can restructure your Git repositories while keeping every bit of your commit history intact using Git's built-in (and highly recommended) git filter-repo tool—this is the modern replacement for the outdated git filter-branch. Let me walk you through exactly how to handle your specific directory setup:
Quick Prerequisite Check
First, make sure each of your VSS-migrated folders (/object/ProjectName/object, /bin/ProjectName/object, /images/ProjectName/object) is already a valid Git repo (you should see a .git folder inside each). All steps below are per-repository, so you’ll repeat them for each of your three repo paths.
Scenario 1: Just Move the Repository (No Internal Structure Changes)
If you only need to relocate the entire repo to /Holder/[target-folder] (like /Holder/object for the first repo) without changing how files are organized inside the repo:
- Move the repo folder to its new home:
# For the object repo mv /object/ProjectName/object /Holder/object # Repeat for the bin and images repos mv /bin/ProjectName/object /Holder/bin mv /images/ProjectName/object /Holder/images - Double-check Git still works:
Hop into the moved repo and run a quick sanity check to confirm history is untouched:
Git doesn’t care about the absolute path of your repo, so this will preserve every commit perfectly—no hoops needed.cd /Holder/object git log --oneline
Scenario 2: Fix Internal Directory Structure (Remove the ProjectName Layer)
If your repo’s internal file paths include the ProjectName folder (e.g., files live under ProjectName/object/xxx inside the repo) and you want to flatten this to /Holder/object/xxx (ditching the ProjectName layer), use git filter-repo to rewrite your commit history cleanly:
- Get git filter-repo:
It’s included with Git 2.22+, but if you’re on an older version, you can grab it directly from the Git project (no installation needed—just make it executable). - Head to your repo’s root:
cd /object/ProjectName/object - Rewrite history to strip out the ProjectName prefix:
This command updates every single commit to remove theProjectName/folder from all file paths:
Note: If the extra layer isgit filter-repo --path-rename ProjectName/:ProjectName/object/instead of justProjectName/, adjust the command togit filter-repo --path-rename ProjectName/object/: - Move the cleaned repo to its target path:
mv . /Holder/object - Validate everything is correct:
Check that your file structure is flat and history is still intact:cd /Holder/object ls -la # Your files should be directly in the repo root now git log --oneline # All old commits should still show up git show <random-commit-hash> # Verify the file paths in old commits match the new structure
Pro Tips to Avoid Headaches
- Backup first!: Always make a full copy of your repos before running history-rewriting commands. Once you rewrite history, old commits are gone for good unless you have a backup.
- Remote repos?: If these repos are pushed to a server (like GitLab or GitHub), you’ll need to force-push the rewritten history with
git push --force. Make sure to tell any collaborators to rebase their local branches instead of pulling—this avoids messy merge conflicts. - Automate it: Since all your repos share the same
ProjectName, you can whip up a quick bash script to run these steps for all three repos at once, saving you time.
内容的提问来源于stack exchange,提问作者advapi

