1' *_* -- 4 git git-rebase git-patch git-rewrite-history
我的一位大学同事认为通过克隆存储库并将其内容复制到新的初始化存储库但没有.git原始存储库中的文件夹来分叉存储库是个好主意.之后,他只使用一次提交就提交了此副本,整个团队就开始根据此提交开发项目:
A <- B <- C <- D <- E (original repository)
\ clone / |_____|
\ / |
\ / Ofc. work on the original repository was continued after cloning...
\ /
M <- N <- O <-P (our "fork", commits from my team)
Run Code Online (Sandbox Code Playgroud)
现在,我的第一个目标是获得以下存储库结构:
A <- B <- C <- N <- O <- P
Run Code Online (Sandbox Code Playgroud)
我在过去几个小时里一直试图做的事情如下:
git diff > /path/to/patch 从叉子里面.git apply 在原始存储库中.A使用将其重置为提交git reset --hard COMMIT_HASH_A.N <- O <- P使用git format-patch COMMIT_HASH_M --stdout > /path/to/patch的叉子.git am -3 /path/to/patch.在解决了几个冲突(例如重复创建空文件)之后,这将导致以下错误:
fatal: sha1 information is lacking or useless (some_file_name).
Repository lacks necessary blobs to fall back on 3-way merge.
这是我无法继续的地方.那么如何创建一个存储库,包括原始存储库和我们团队的所有提交,如上所述,最终拉取请求可以发送到原始存储库?可以git-rebase帮忙吗?
在您的原始 repo 克隆中,您应该:
git remote add colleague /path/to/colleague
git fetch colleague
git checkout -b colleague colleague/master
git rebase master
git checkout master
git merge colleague
Run Code Online (Sandbox Code Playgroud)
这将为您提供线性历史记录,并且不会留下冗余且无父级的M提交。
这与David Siro's answer不同,后者将产生一个合并提交,同时M在您合并的分支中留下一个冗余/无父提交。我不喜欢那种悬空提交的场景。
我复制了你好的和坏的存储库历史,并且能够通过基本上重新设置远程来解决问题。
这些是我遵循的步骤:
master分支通过该设置,我使用的命令和关键输出如下。
#
# Step 1
#
$ git clone <path-to-original-repo>
$ cd original-repo
#
# Step 2
#
$ git remote add messed-up-repo <path-to-messed-up-repo>
#
# Step 3
#
$ git fetch messed-up-repo
#
# Step 4
#
$ git checkout -b bad-master bad-orig/master
#
# Step 5
#
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: commit M
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
No changes -- Patch already applied.
Applying: commit N
Applying: commit O
Applying: commit P
#
# Step 5.1: look at your new history
#
$ git log --oneline --graph --decorate
* cc3121d (HEAD -> bad-master) commit P
* 1144414 commit O
* 7b3851c commit N
* b1dc670 (origin/master, origin/HEAD, master) commit E
* ec9eb4e commit D
* 9c2988f commit C
* 9d35ed6 commit B
* ae9fc2f commit A
#
# Step 6
#
$ git checkout master
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.
$ git merge bad-master
Updating b1dc670..cc3121d
Fast-forward
n.txt | 1 +
o.txt | 1 +
p.txt | 1 +
3 files changed, 3 insertions(+)
create mode 100644 n.txt
create mode 100644 o.txt
create mode 100644 p.txt
#
# Step 7
#
$ git push
Counting objects: 9, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (6/6), done.
Writing objects: 100% (9/9), 714 bytes | 0 bytes/s, done.
Total 9 (delta 3), reused 0 (delta 0)
To /tmp/repotest/good-orig.git
b1dc670..cc3121d master -> master
#
# Step 7.1: look at your history again
#
$ git log --oneline --graph --decorate
* cc3121d (HEAD -> master, origin/master, origin/HEAD, bad-master) commit P
* 1144414 commit O
* 7b3851c commit N
* b1dc670 commit E
* ec9eb4e commit D
* 9c2988f commit C
* 9d35ed6 commit B
* ae9fc2f commit A
Run Code Online (Sandbox Code Playgroud)
您现在可以用火销毁同事的混乱存储库,并让其他人继续使用原始的、现在已修复的存储库。
注意:在你的帖子中,你说你想要提交:
Run Code Online (Sandbox Code Playgroud)A <- B <- C <- N <- O <- P
但我的解决方案包括提交D和E中间:A <- B <- C <- D <- E <- N <- O <- P。如果你真的想扔掉这些提交,即假设它不是你的帖子中的错字,那么你可以简单地git rebase -i HEAD~5删除pick这些提交的行,然后git push --force到你的好仓库的来源。
我假设您了解重写历史记录的含义,并且您需要与您的用户进行交流,以免他们受到影响。
为了完整起见,我按如下方式复制了您的设置:
A <- B <- CM <- N <- O <- P,其中M与原始内容相同A <- B <- C... C <- D <- E如果您不坚持线性历史记录,则可以将fork合并到原始存储库中.
在原来的repo drirectory:
git remote add fork /path/to/fork
git fetch fork
git merge fork/master
Run Code Online (Sandbox Code Playgroud)
如果可以快速转发合并,这将保留提交并可能导致班轮历史记录(无合并提交).
| 归档时间: |
|
| 查看次数: |
664 次 |
| 最近记录: |