a
上。我想在分支b
上提交代码,这样克隆分支b
的人就能和我的当前工作目录一样了。因为有时候暂存当前更改会导致冲突,所以无法使用stash命令。
我正在寻找与创建工作目录临时副本相当的方法。具体做法是:先将工作目录复制一份到其他位置,然后执行
git checkout -f b
切换到分支b
,再删除所有文件,最后将之前复制出的工作目录拷贝到项目目录并提交代码。a
上。我想在分支b
上提交代码,这样克隆分支b
的人就能和我的当前工作目录一样了。git checkout -f b
切换到分支b
,再删除所有文件,最后将之前复制出的工作目录拷贝到项目目录并提交代码。如果你想让B版本之后的修订版本与你当前的工作树(即现在未提交)保持一致,可以使用git reset --soft命令:
最初的回答:
git reset --soft如果您的朋友。 如果您希望B版本之后的修订版本与您在工作树上拥有的版本相同(即目前尚未提交),则可以执行此操作:
git checkout --detach # disconnect from A
git reset --soft b # set the branch pointer to whatever revision B is pointing to.... Your working tree will be unaffected
git add . # add everything to index
git commit -m "revision after B that made it look the way I had it where I was working"
# if you like everything, move b branch to this revision and push
git branch -f b
git checkout b
git push some-remote b
最初的回答。
git show <commit>
命令时,你要查看的实际上是快照中的“变更差异”。关于分支 b
的历史重写
如果你想让分支 b
上的提交反映出此刻分支 a
的确切状态,为什么不直接将分支 b 指向应该指向的位置呢?就像这样:
# get the uncommited changes on the branch
git commit -am "Useful message"
# point b where a is now
git branch -f b a
# instead of forcing the branch we could merge with a strategy ours
# but it's hard to tell what you need from your description alone
# reset a to its previous state
git reset --hard HEAD^
C1---C2 <<< a <<< HEAD # with a dirty tree, uncommited changes
? <<< b # (you didn't mention where b was pointing)
之后的结果
C1---C2 <<< a <<< HEAD
\
C3 <<< b # where your last (previously uncommited) changes are
不重写分支 b
的历史记录
为了避免重写分支 b
的历史记录,一种替代方法是使用一种策略将 a
合并到 b
中,这种策略将从 a
方面获取所有内容,而不仅仅是冲突部分。操作步骤如下:
# we work on a copy of branch a
git checkout -b a-copy a
# get the uncommited changes on the branch
git commit -am "Useful message"
# proceed with the merge, taking nothing from b
git merge -s ours b
# we now reflect the merge on b, and this is a fast-forward
git checkout b
git merge a-copy
# no further need for the working copy of a
git branch -D a-copy
而且 a
不需要重置,因为它没有在任何时候移动。
第一次提交后:
C1---C2 <<< a
\
C3 <<< a-copy <<< HEAD
o <<< b (anywhere in the tree)
第一次合并后:
C1---C2 <<< a
\
C3 (same state as a, plus the previously uncommited changes)
\
C4 <<< a-copy <<< HEAD (the merge taking only C3 side)
/
o <<< b (anywhere in the tree)
C1---C2 <<< a
\
C3 (same state as a, plus the previously uncommited changes)
\
C4 <<< b <<< HEAD
/
o
b
的历史记录吗?这样只需添加一个提交。 - Toastgit stash
确实保存了当前的工作目录。问题在于它保存的方式不直接适合您的需求。还有一个次要问题,可能是一个非常严重的问题,但也可能很小。请参见下面的警告。但最终,您可能能够使用git stash
来完成您想要的操作。
git add
,覆盖索引中的副本,然后才能提交此更改。当然,这会破坏您在索引中进行的任何仔细分阶段。git stash
实际上会生成两个提交的原因:
(实际上,还有第三个可选提交来保存未跟踪或未跟踪加忽略的文件。如果存在该提交,则它是工作树提交的第三个父级。通常它不存在。)
完成这两个提交后,git stash
会更新refs/stash
以记住工作树提交w
的哈希ID。该提交记住了索引提交i
的哈希ID,以及当前提交的哈希ID:
...--o--o--T <-- your-branch (HEAD)
\ |\
\ i-w <-- refs/stash
\
o--A <-- b
git stash
运行git reset --hard
,以便您的索引和工作树返回匹配提交T
。我已经突出显示了另一个提交A
,由其他分支b
指向。
1从技术上讲,git stash
会使用第二个辅助/临时索引来创建提交 w
,以防万一出现问题。在那种情况下,它可以放弃临时索引。然而,制作索引提交 i
非常容易,因为管道命令 git write-tree
完成所有工作。
需要注意的是:git stash
实际上只会对已经在索引中的所有文件执行 git add
操作。任何未被跟踪的文件,包括未被跟踪且被忽略的文件,都不在提交 w
中。它们就在你的工作目录中。即使在这种情况下,如果你执行了 git checkout A
来切换到提交 A
,其中一些文件也将被复制到你的索引中。(当然,在这种情况下,你通常会看到 Git 需要覆盖某些未被跟踪的文件的警告。)
除了这个重要的注意事项外,储藏提交 w
的快照恰好是你想要添加到提交 A
后面的快照。
现在,既然这个快照存在了,你可以告诉 Git 创建一个新的提交 B
,它以提交 A
为父提交,以 w
的树对象为其快照。这需要一个 Git 的内部命令:
git commit-tree -p refs/heads/b refs/stash^{tree}
也就是说,我们使用名称 refs/heads/b
(分支 b
,指向提交 A
)来告诉 Git 我们新提交的父级哈希 ID 应该是什么。我们使用 refs/stash^{tree}
来告诉 Git 我们新提交的树(快照)应该是什么。Git 读取标准输入以收集日志消息 - 如果您愿意,可以添加 -m <message>
或 -F <file>
来提供消息,或将其发送到标准输入:
echo some message | git commit-tree -p refs/heads/b refs/stash^{tree}
这是结果。
...--o--o--T <-- your-branch (HEAD)
\ |\
\ i-w <-- refs/stash
\
o--A <-- b
\
B
新提交B
的快照与贮藏提交w
相同。
git commit-tree
命令打印出新提交的哈希ID。你需要将其存储在一个shell变量中,然后很可能设置一些名称,例如refs/heads/b
,以记住此提交。例如:
hash=$(git commit-tree -p refs/heads/b refs/stash^{tree})
git update-ref -m "add stashed work-tree commit" refs/heads/b $hash
提供:
...--o--o--T <-- your-branch (HEAD)
\ |\
\ i-w <-- refs/stash
\
o--A--B <-- b
git commit-tree
的任何内容。 B的哈希ID现在存储在b中,并且B的父级是A,因此这个新提交位于分支b上,就像您想要的那样。git stash push # and make sure it does something
hash=$(echo automatic commit of work-tree |
git commit-tree -p refs/heads/b refs/stash^{tree})
git update-ref -m "add stashed work-tree commit" refs/heads/b $hash
git stash pop --index
git stash push
说没有要保存的内容时,拒绝执行任何操作)。
i
读入索引的方式效率低下,但达到了相同的目的。对于w
步骤也是如此。git write-tree
、git commit-tree
和git update-ref
将提交放到分支b
上)更加高效。您可以通过使用临时索引来解决前面的问题,就像git stash
所做的那样。但这不会说明为什么您可以使用git stash
来获得您想要的结果。 :-) - torek
1;进行你的提交;git push --force;再次切换到分支a;git reset HEAD1;就这样。 - ovimunt