我在主分公司的大学项目上工作了一段时间。
在每一步我们都应该添加TAG。但是我最近发现我必须在之前的标签中修改一些东西。
我搜索过,我找到了很多解决方案(基于重置 - 硬件或其他东西),但我不想失去我所做的一切,特别是我必须做的编辑非常小。
我知道我们不应该更改标签中的任何内容,但我必须进行的编辑是次要的。
那么在旧提交中编辑文件(制作标签)的最佳方法是什么,而不会在提交后丢失更改?
谢谢
答案 0 :(得分:0)
你不能。你可以可以做一些事情(在线下),但你要求的几乎是不可能的。原因很简单,虽然它分为两部分:
标记只是提交的名称。 (它可能是"带注释的标记对象的名称"它反过来命名一个提交,但这最终都是相同的。)
每个提交 - 实际上,每个Git对象 - 由其哈希ID唯一标识。命令git rev-parse
将名称(例如分支和标记名称)转换为这些哈希ID:
$ git rev-parse origin/master
659889482ac63411daea38b2c3d127842ea04e4d
$ git rev-parse v2.2.1
7c56b20857837de401f79db236651a1bd886fbbb
使用标记(例如v2.2.1
)而不是哈希ID的主要原因是......嗯,谁能记住7c5b208-aw-the-heck-with-it
,我们将如何将其与{{1}进行比较}}?我知道:电脑可以为我们记住这个!让我们让计算机记住哈希ID,并将其称为"标记"。
标记名称和分支名称之间的区别在于标记假定永远保持不变,并且分支假定移动,在&中#34;前进一步"当你做出提交的时尚--Git会自动为你做这件事 - 或者有时会在很多提交中快速做到这一点"时尚(当你从其他地方获取新的更新时)。
提交的原始哈希ID是该提交内容的加密校验和。事实上,对于所有Git对象都是如此:哈希是SHA-1内容校验和。如果您在Git存储的任何内容中更改了一个位,您将获得一个新的不同的哈希ID。
任何提交的内容都取决于该提交中的所有文件,以及导致该提交的所有历史记录。我发现查看实际提交是有益的:
v2.5.2
它实际上是$ git cat-file -p origin/master | sed 's/@/ /'
tree 3424a8d14d91a3aaf7b9d5c962f5dd36ff90953c
parent 720265749d905ab8da275f18abc42b2dac751dff
parent 23415c26fef155f2fa9aebf8a48a6ae457b68c7b
author Junio C Hamano <gitster pobox.com> 1476737546 -0700
committer Junio C Hamano <gitster pobox.com> 1476737546 -0700
Sync with maint
* maint:
l10n: de.po: translate 260 new messages
l10n: de.po: fix translation of autostash
l10n: ru.po: update Russian translation
行(指向Git&#34;树&#34;对象),它允许提交记录源的快照。如果更改源,tree
对象及其ID将更改,这意味着新提交(使用新的和不同的tree
对象的提交)与旧提交不同。
因为ID是内容的加密校验和,所以没有Git对象可以永远更改。 Git通常只将 new 对象添加到存储库中;现有的物体永远保持不变,物体几乎不会被删除(我们稍后会看到更多)。
所有这一切 - 您无法编辑现有提交中的文件 - 您可以制作新和不同的提交*,然后为它命名。如果删除标记的旧名称到ID映射,并安装这个新的,不同的名称到ID映射,该怎么办?这被称为&#34;重新标记&#34;和Linus Torvalds has advice for the re-tagger, right in the git tag
documentation:
当您标记错误的提交并且想要重新标记时,您应该怎么做?
如果您从未推过任何东西,只需重新标记即可。使用&#34; -f&#34;替换旧的。你已经完成了。
但是如果你把事情搞砸了(或者其他人可以直接读取你的存储库),那么其他人就已经看到了旧的标签。在这种情况下,您可以执行以下两项操作之一:
理智的事情。只是承认你搞砸了,并使用不同的名字。其他人已经看过一个标签名称,如果你保持相同的名称,你可能会遇到两个人都拥有&#34;版本X&#34;但他们实际上有不同的 &#34; X&#34;&#39;第所以只需称它为&#34; X.1&#34;并完成它。
- 醇>
疯狂的事。 ...
(点击链接阅读其余部分。)
如果你想做一个像旧提交一样的新提交,但是有一些改变,你有一些选择。让我们从这开始:像往常一样,像往常一样在分支上进行新的提交。
首先给自己一个指向原始提交的分支名称:
tree
(我们在这里所做的只是为before:
...--o--o--o--o--o--o <-- master
^
|
tag: v2.5.2
$ git checkout -b newbranch v2.5.2
now: o--o--o <-- master
/
...--o--o--o <-- newbranch
^
|
tag: v2.5.2
推了一些链,然后添加一个新的分支标签master
,指向与标签相同的提交 newbranch
)。
现在v2.5.2
上的提交会像往常一样延长newbranch
:
newbranch
如果您使用了多少次提交来扩展 o--o--o <-- master
/
...--o--o--o--o--o <-- newbranch
^
|
tag: v2.5.2
,则可以重新标记(强制newbranch
指向新提示提交),或创建新标记。使用Linus的建议知道哪些是明智的。
除此之外,您可能已阅读v2.5.2
。这个似乎来更改提交。这是一个谎言 - 在好的情况下是一个白色的谎言,在其他一些情况下是一种灰色或暗淡的谎言;如果你不知道它的真正作用,它会在恶劣的情况下恶毒地咬你。
git commit --amend
做的是修改进行新提交的正常过程。 正常进程是将新提交添加到当前分支:
git commit --amend
before:
...--A--B--C <-- branch
$ git commit ...
after:
...--A--B--C--D <-- branch
做的是将当前提交推到一边,以便&#34;&#34;之后&#34;这张照片的一部分看起来像这样:
git commit --amend
请注意,提交 C [abandoned]
/
...--A--B--D <-- branch
(C
的上一个提示)完全未修改。它存在于您的存储库内部,完整且未更改,直到稍后的垃圾收集&#34; pass(branch
)发现它是否真的被抛弃了。默认情况下,名为 reflog 的东西会挂起至少30天,这样如果您发现自己需要它,就可以将其取回;如果有一些其他分支或标记名称,Git可以通过它找到提交git gc
某些其他方式,那些挂起到提交&#34;永远&#34; (或直到那些分支和/或标签名称都被删除)。
让我们来看看如果我们使用&#34;将提交推到一边会发生什么?&#34; &#34;&#34;之后的C
方法看起来像这样的图片:
newbranch
如果需要,我们会 o--o--o <-- master
/
...--o--o--o <-- newbranch
^
|
tag: v2.5.2
,以便我们对其进行处理。然后,我们会在工作树git checkout newbranch
和git add
中进行一些更改。这会将标记的提交推到一边,但git commit --amend
仍然链接到它,并且标记仍然指向它。绘图会变得混乱,所以让我们在每次提交时都放置一个字母的名字,暂时停止在标签中绘图。这是&#34;在修改之前&#34;再次拍照,字母名称为:
master
现在我们进行&#34;修改&#34;,将C推到一边。但是, D--E--F <-- master
/
...--A--B--C <-- newbranch
仍然指向D
,因此我们在C
所在的地方绘制了新的提交G
,但将C
移开了C
指向它。请注意,D
仍然指向C
:
B
现在我们可以再次绘制标记 - 它仍然指向提交 C--D--E--F <-- master
/
...--A--B--G <-- newbranch
,所以让我们从上面绘制它:
C
事实上,完全以另一种方式绘制它可能会更好:
tag: v2.5.2
|
v
C--D--E--F <-- master
/
...--A--B--G <-- newbranch
现在很清楚 tag: v2.5.2
|
v
...--A--B--C--D--E--F <-- master
\
G <-- newbranch
怎么没有修改任何东西。它所做的是在--amend
进行新的提交newbranch
时将风G
退回一步,以便G
指回B
,而不是指向C
。
此时,您可以重新标记&#34;重新标记&#34;您的旧标记(如果这是一个理智的事情),或者只是创建一个指向提交G
的新标记。