简体   繁体   English

如何停止跟踪 git 中的文件一段时间?

[英]how to stop tracking files in git for sometime?

I want git to stop tracking some files in git for generating pull requests in bitbucket. I am not an administrator so cannot do the changes in bitbucket. Is there a good way to do it?我想让 git 停止跟踪 git 中的一些文件,以便在 bitbucket 中生成拉取请求。我不是管理员,所以无法在 bitbucket 中进行更改。有什么好的方法吗? I understand I can use "git rm --cached ", but i want it for whole directories and some files which I would like to set it back again to normal after pull request has been done.我知道我可以使用“git rm --cached”,但我希望它用于整个目录和一些文件,我想在完成拉取请求后将其重新设置为正常。 I changed.gitignore file, but that's only for untracked.我更改了 .gitignore 文件,但这仅适用于未跟踪的文件。 So, its still showing the changes.所以,它仍然显示出变化。 Please help.请帮忙。

A tracked file, in Git, is a file that is in Git's index. Git 中的跟踪文件是 Git 索引中的文件。

That's the entire definition right there.这就是完整的定义。 So git rm --cached , which removes a file from Git's index, will indeed make it not be tracked.所以git rm --cached从 Git 的索引中删除一个文件,确实会使它不被跟踪。 But that's probably not what you want, because Git makes new commits from whatever is in Git's index at the time you run git commit .但这可能不是您想要的,因为 Git 在您运行git commit时从 Git 索引中的任何内容进行提交。 Unless you're not making any new commits, the fact that these new commits omit the file means that, as compared to any commit that has the file, the file has been "deleted".除非您不进行任何新提交,否则这些新提交省略文件的事实意味着,与具有该文件的任何提交相比,该文件已被“删除”。

Hence, removing the file from the index is only an option if you're not going to make new commits—in which case, whether the file is tracked or not is probably not relevant in the first place.因此,如果您不打算进行新的提交,从索引中删除文件只是一个选项——在这种情况下,文件是否被跟踪可能首先是不相关的。

The trick here is to understand that you do not actually want to stop tracking the file .这里的技巧是了解您实际上并不想停止跟踪该文件 Instead, you want, in new commits you make, to use the same file that you had in some previous commit , regardless of how the file looks in your working tree .相反,您希望在您所做的提交中使用您在之前的某个提交中拥有的相同文件,而不管该文件在您的工作树中的外观如何。 That's pretty easy to do, but before you can understand how this works, we need to define a lot of the jargon terms I just used.这很容易做到,但在您理解其工作原理之前,我们需要定义很多我刚刚使用的行话。

What to know about a Git commit关于 Git 提交的知识

A commit, in Git:提交,在 Git 中:

  • is numbered, though the number looks random;已编号,尽管数字看起来是随机的;
  • contains a snapshot of every file (as found in Git's index: more on this below);包含每个文件的快照(在 Git 的索引中找到:更多信息见下文); and
  • contains some metadata.包含一些元数据。

The commit's number is a weird, random-looking (but not actually random) and very large number (between 1 and 2 160 -1, or about 1.4 quindecillion in the short scale system ), normally expressed in hexadecimal .提交的数字是一个奇怪的、随机的(但实际上不是随机的)并且非常大的数字(在 1 和 2 160 -1 之间,或者在短尺度系统中大约为 1.4 五分之一),通常以十六进制表示 Every commit in every Git repository gets a unique number, which is why these have to be so big: any commit you make will have a different number than every other commit ever .每个Git 存储库中的每个提交都有一个唯一的编号,这就是为什么这些编号必须如此之大:您所做的任何提交都将具有与以往所有其他提交不同的编号。 This is how Git can tell if two different repositories have the same commit: two commits are only the same if they have the same number .这就是 Git 如何判断两个不同的存储库是否具有相同的提交:两个提交只有在它们具有相同的数字时才相同。

The snapshot in a commit is the complete set of all files, as seen in Git's index.提交中的快照是所有文件的完整集合,如 Git 索引中所示。 These files are stored in a special, Git-only, compressed and de-duplicated format.这些文件以特殊的、仅限 Git、压缩和去重的格式存储。 The de-duplication takes care of the fact that most commits actually share most of their files with other commits: these files are only actually stored once.重复数据删除处理了这样一个事实,即大多数提交实际上与其他提交共享他们的大部分文件:这些文件实际上只存储一次。

The metadata in a commit contains things like the name and email address of the person who made the commit, and the date-and-time of when they made that commit.提交中的元数据包含提交人的姓名和 email 地址,以及提交人的日期和时间 It also contains the raw commit number of some earlier commit (as long as there is some earlier commit).它还包含一些较早提交的原始提交编号(只要有一些较早的提交)。 This is what glues commits together.这就是粘合在一起的东西。

Since the actual hash IDs—the commit numbers—of real commits are so big and ugly, let's draw a tiny repository, with just three commits in it, by pretending that the commit's "numbers" are A , B , and C , in that order.由于实际提交的实际 hash ID(提交编号)又大又丑,让我们绘制一个小型存储库,其中只有三个提交,假设提交的“编号”是ABC ,在那个命令。 Commit A , being the very first commit ever, doesn't have any previous commit, so it just sits there:提交A是有史以来的第一个提交,之前没有任何提交,所以它只是坐在那里:

A

Commit B , however, has commit A as its previous commit, so it points backwards to A :但是,提交B将提交A作为其先前的提交,因此它向后指向A

A <-B

Commit C likewise points backwards, but to B :提交C也同样向后指向,但是指向B

A <-B <-C

Each commit stores a full snapshot of every file, so by extracting—say—commits B and C and comparing the files thus extracted, Git can tell you what changed between B and C .每个提交存储每个文件的完整快照,因此通过提取提交BC比较提取的文件,Git 可以告诉您BC之间发生了什么变化

All parts of any commit, once made, are completely and totally read-only.任何提交的所有部分一旦完成,都是完全只读的。 No part of any commit can ever be changed, Commits are mostly permanent (they only go away, eventually, if you can't find them—we'll say more about this in a moment) and are totally read-only.任何提交的任何部分都不能更改,提交大多是永久性的(它们只有 go 远,最终,如果你找不到它们——我们稍后会详细说明)并且完全是只读的。

Branch names分行名称

Now, because commit hash IDs are so big and ugly, we (humans) never want to have to use them.现在,因为提交 hash ID 又大又丑,我们(人类)永远不想使用它们。 So to help us out, Git gives us branch names .所以为了帮助我们,Git 给了我们分支名称 A branch name is just a way to store the hash ID of one (1) commit.分支名称只是一种存储一 (1) 次提交的 hash ID 的方法。 We say that the branch name points to the commit, and I like to draw that like this:我们说分支名称指向提交,我喜欢这样画:

A--B--C   <-- main

Note that I get lazy about drawing the arrows between commits.请注意,我懒得在提交之间绘制箭头。 They actually point backwards (from C back to B , then from B to A ) but humans tend to like to pretend they go forwards.他们实际上指向后方(从C回到B ,然后从BA )但人类倾向于假装他们 go 向前。 This mostly doesn't matter so it's mostly OK to not bother drawing them in properly anyway, but you should remember that Git actually works backwards.这基本上无关紧要,所以无论如何都不必费心正确地绘制它们,但你应该记住 Git 实际上是倒过来的。 (It helps out with other things later. We won't need to worry about it here though.) (它有助于稍后处理其他事情。不过我们在这里不需要担心。)

The name main (or master ) currently selects commit C .名称main (或master )当前选择提交C But this isn't permanent: if we git checkout main , we select commit C .但这不是永久性的:如果我们git checkout main ,我们select提交C Then, we do various things to get ready to make a new commit.然后,我们做各种事情来准备进行的提交。

When we do go to make a new commit by running git commit , Git will:当我们通过运行 go 进行新提交时git commit , Git 将:

  1. package up all the files in Git's index (again, more about this in a moment) into a new mostly-permanent snapshot, all de-duplicated as appropriate; package 将 Git 索引中的所有文件(同样,稍后会详细介绍)放入一个新的几乎永久的快照中,并根据需要删除所有文件;
  2. add your name and email address and other metadata as needed;根据需要添加您的姓名和 email 地址以及其他元数据;
  3. use the current commit's raw hash ID as the parent for the new commit, so that the new commit points back to the current commit;使用当前提交的原始 hash ID 作为新提交的提交,以便新提交指向当前提交;
  4. write all this out so as to make the new commit, which also acquires the new commit's new hash ID;写出所有这些以进行新的提交,该提交还获取新提交的新 ID hash; and finally最后
  5. write this new commit's hash ID into the current branch name .将这个新提交的hash ID写入当前分支名称

Since there can be multiple branch names in a repository, Git remembers which name is the current branch name by attaching the special name HEAD to just one branch name.由于存储库中可以有多个分支名称,Git 通过将特殊名称HEAD附加到一个分支名称来记住哪个名称是当前分支名称。

Let's draw this.让我们画这个。 Suppose we have:假设我们有:

A--B--C   <-- main (HEAD)

Now we create a new branch name, such as dev for develop.现在我们创建一个的分支名称,例如 develop 为dev This branch name must point to some existing commit.此分支名称必须指向某个现有的提交。 Which one should we choose?我们应该选择哪一个? We can pick any existing commit, A through C , but the obvious one to choose right now is the current one, C :我们可以选择任何现有的提交, AC ,但现在明显要选择的是当前提交, C

A--B--C   <-- dev, main (HEAD)

Note how both branch names pick the same commit .请注意两个分支名称如何选择相同的提交 So if we now switch the current branch to commit C , like this:因此,如果我们现在将当前分支切换到提交C ,如下所示:

A--B--C   <-- dev (HEAD), main

nothing else has to change, and in fact, nothing else does change.没有其他需要改变,事实上,没有其他改变。

Now we prepare a new commit—in the way we'll think and talk more about in a moment—and we run git commit .现在我们准备一个新的提交——以我们稍后会思考和讨论的方式——我们运行git commit Git packages up the files, adds the metadata, and makes a new commit D that points back to existing commit C : Git 打包文件,添加元数据,并创建一个新的提交D指向现有提交C

A--B--C
       \
        D

What happens with the branch names?分支名称会发生什么? We just said: Git writes the new commit's hash ID into the current branch name , the one HEAD is attached to.我们刚才说: Git 将提交的 hash ID 写入当前分支名称,一个HEAD附加到。 Nothing else happens to any other branch name.任何其他分支名称都不会发生任何其他情况。 So now we have:所以现在我们有:

A--B--C   <-- main
       \
        D   <-- dev (HEAD)

Commit D is our new commit;提交D是我们的新提交; commits ABC are our existing commits;提交ABC是我们现有的提交; D points back to C ; D点回C and main still points to C because it has not moved, but dev now points to our new commit D because our current branch is dev .并且main仍然指向C因为它没有移动,但是dev现在指向我们的新提交D因为我们当前的分支dev

If you git checkout main or git switch main , Git will remove the files that go with commit D and extract the files that go with commit C .如果您git checkout maingit switch main ,Git 将删除 go 提交D的文件,并提取 go 提交C的文件 That's because by changing branches, you've changed which commit you're using:那是因为通过更改分支,您已经更改了您正在使用的提交

A--B--C   <-- main (HEAD)
       \
        D   <-- dev

If you want the commit- D files back, you git checkout dev , which currently means commit D .如果你想要 commit- D文件,你git checkout dev ,这当前意味着commit D The branch names move!分支名称移动! The commits don't move: they're read-only (completely) and permanent (mostly).提交不会移动:它们是只读的(完全)和永久的(大部分)。 We find them using the branch names, and then—if needed—working backwards.我们使用分支名称找到它们,然后(如果需要)向后工作。

Let's check out dev again and make one more commit, then switch back to main , then make a new branch feature and switch to feature :让我们再次检查dev并再次提交,然后切换回main ,然后创建一个新的分支feature并切换到feature

        D--E   <-- dev
       /
A--B--C   <-- feature (HEAD), main

I drew dev on top this time just because I want our new commits to go on the bottom row.这次我把dev画在上面只是因为我希望我们的新提交到底行的 go。 The names feature and main both select commit C right now, and the files we have to work with are those from commit C .名称featuremain都是 select 现在提交C ,我们必须使用的文件来自提交C We make some changes and add and commit and get a new commit F :我们进行一些更改并添加并提交并获得新的提交F

        D--E   <-- dev
       /
A--B--C   <-- main
       \
        F   <-- feature (HEAD)

If we make another commit, we end up with:如果我们再次提交,我们最终会得到:

        D--E   <-- dev
       /
A--B--C   <-- main
       \
        F--G   <-- feature (HEAD)

All we ever really do is add commits .我们真正做的就是添加提交 The existing commits remain.现有的提交仍然存在。 We can check them out—by name, with git checkout main for instance, or by raw hash ID (resulting in what Git calls a detached HEAD )—and we can make new commits.我们可以检查它们——通过名称,例如git checkout main ,或者通过原始 hash ID(导致 Git 称之为分离的 HEAD )——我们可以进行新的提交。 We can never change any existing commit.我们永远无法更改任何现有的提交。

You now know what branches are in Git. But there's more to learn.您现在知道 Git 中有哪些分支。但还有更多内容需要学习。

Git's index and your working tree Git 的索引和你的工作树

You have made commits before, so you know that you run git checkout , edit some file(s), run git add , and then run git commit .您之前已经提交,所以您知道您运行git checkout ,编辑一些文件,运行git add ,然后运行git commit (Or, maybe you used the slightly sleazy short-cut, git commit -a .) Your Git tutorial(s) may have mentioned the index or the staging area . (或者,也许您使用了稍微低级的快捷git commit -a 。)您的 Git 教程可能提到了索引临时区域 Unless they were pretty good tutorials, though, they probably didn't cover it properly.但是,除非它们是非常好的教程,否则它们可能没有正确涵盖它。

Covering this thing properly is essential, because the index is the key to everything here.适当地覆盖这个东西是必不可少的,因为索引是这里一切的关键。 Of course, the name index is pretty poor.当然,名称索引很差。 It's so bad, in fact, that Git has two other names for it.它是如此糟糕,事实上,Git 还有另外两个名字 The name staging area , which might be what your tutorials used, is another name for the index.名称staging area可能是您的教程使用的名称,是索引的另一个名称。 The third name—pretty rare these days—is the cache;第三个名字——现在很少见——是缓存。 this name mostly turns up in flags like git rm --cached .这个名字主要出现在像git rm --cached这样的标志中。 All three names refer to the same thing.这三个名字指的是同一个东西。 But: what is this thing?但是:这什么东西?

We already mentioned that the files inside a commit are stored in a special, compressed, read-only, Git-only, de-duplicated format.我们已经提到,提交中的文件以特殊的、压缩的、只读的、Git-only、去重的格式存储。 Only Git can read these files, and literally nothing can write them, not even Git itself.只有Git可以读取这些文件,实际上没有任何东西可以写入它们,甚至 Git 本身也不能。 (Git can create new ones, but not overwrite existing ones. The hash ID tricks that Git uses require this, so even if it's physically possible to overwrite them—the OS usually doesn't prevent it—that just breaks the repository, and then everyone is sad and out of work and we starve to death, or something else miserable out of a Chinese film.) (Git 可以创建的,但不能覆盖现有的。Git 使用的 hash ID 技巧需要这个,所以即使覆盖它们在物理上是可能的——操作系统通常不会阻止它——这只会破坏存储库,然后每个人都很伤心,失业了,我们饿死了,或者中国电影中的其他悲惨经历。)

How, then, can we ever get any work done?那么,我们怎样才能完成任何工作呢? To get work done, we need ordinary read/write files, that we can read and write.为了完成工作,我们需要可以读写的普通读/写文件。 So Git will extract the files from a commit.所以 Git 将从提交中提取文件。 Indeed, pretty much all version control systems work this way: you take the committed files out of the VCS and turn them into regular files that you then work with.事实上,几乎所有的版本控制系统都是这样工作的:你把提交的文件从 VCS 中取出来,然后把它们变成你可以使用的常规文件。

This explains your working tree .这解释了你的工作树 Your working tree is where you have your files, to work with however you like.您的工作树是拥有文件的地方,可以随心所欲地使用。 Once the files are out of Git, Git is hands-off on these things.一旦文件从 Git 中取出,Git 就会放手处理这些事情。 Those are now your files, unless and until you tell Git do something with them, like replace them with files from some other commit.这些现在是你的文件,除非并且直到你告诉 Git 对它们做一些事情,比如用来自其他提交的文件替换它们。

But what about the index?但是索引呢? Why is there this mysterious "staging area" thing?为什么会有这个神秘的“集结区”这个东西? Other version control systems don't seem to have one—and indeed, most don't, or at least don't whack you in the face with it, the way Git does.其他版本控制系统似乎没有——事实上,大多数没有,或者至少不会像 Git 那样用它来打你的脸。 So it's not necessary , but Git has it, and Git will whack you in the face with it.所以没有必要,但是 Git 有,Git 会用它来打你的脸。 You'd better know about it.你最好了解一下。

What Git does with this staging area is pretty simple: Git 对这个暂存区的作用非常简单:

  • When you check out a commit, Git copies the commit's files into the staging area .当您检出提交时,Git 会将提交的文件复制到暂存区 These files are in the special read-only de-duplicated format, so they don't actually take any space (though there's a modest amount of space per file, on the order of 100 bytes or so, for cache data that Git wants here).这些文件采用特殊的只读去重格式,因此它们实际上不占用任何空间(尽管每个文件的空间量适中,大约 100 字节左右,用于 Git 在这里需要的缓存数据).

  • These files, being in the compressed-and-de-duplicated format, are ready to go into the next commit .这些文件采用压缩和去重格式,已准备好 go 进入下一次提交 That is, the staging area, right now, at this point, consists of the current commit , which is ready to be the next commit.也就是说,暂存区,此时此刻,由当前提交组成,它已准备好成为下一个提交。

  • Git also copies the files from the commit/staging-area to your working tree, expanding them into normal usable files, so that you can work with them. Git 还将文件从提交/暂存区复制到您的工作树,将它们扩展为正常可用的文件,以便您可以使用它们。

Once you've worked with a file and it's ready to be updated, Git makes you run git add on the file.一旦你处理了一个文件并准备好更新它,Git 会让你运行git add文件。 This:这:

  • reads the working tree copy, compressing it and turning it into the internal Git form;读取工作树副本,将其压缩并将其转换为内部 Git 形式; and
  • checks to see if it's a duplicate.检查它是否重复。

If it is a duplicate, Git then puts into the index the duplicate "copy", which takes no space, just as before.如果它重复的,Git 然后将重复的“副本”放入索引中,它不占用空间,就像以前一样。 This file is now ready to be committed.该文件现在可以提交了。

If it's not a duplicate, Git puts the ready-to-go file into the index (though technically Git puts it elsewhere and puts just a reference to it into the index, so that it looks pretty much the same as if it were a duplicate).如果它不是重复的,Git 将准备好的文件放入索引中(尽管从技术上讲 Git 将它放在其他地方并仅将对它的引用放入索引中,因此它看起来几乎与重复的一样).

Either way, this file is now ready to be committed —along with every other file that's already in the index.不管怎样,这个文件现在已经准备好提交了——连同索引中已经存在的所有其他文件 The old version of the file, if there was one, has been booted out of the index;文件的旧版本(如果有的话)已从索引中删除; now the current version is ready to commit.现在当前版本已准备好提交。

So git add just copies the file into Git's index , making it ready to commit.所以git add只是将文件复制到 Git 的索引中,使其准备好提交。 The index continues to hold the proposed next commit .该索引继续保存建议的下一次提交 This means that, at all times, the index holds your proposed next commit .这意味着,在任何时候,索引都会保存您建议的下一次提交 That's what the index really is, mostly: your proposed next commit.这就是索引的真正含义,主要是:您提议的下一次提交。 (During conflicted merges, the index takes on an expanded role, but Git also won't let you commit, so it's still sort of your proposed but not-commit-able commit even then. We won't go into further detail here, so we can just leave it at "proposed next commit".) (在有冲突的合并期间,索引扮演了一个扩展的角色,但是 Git 也不会让你提交,所以即使那样它仍然是你提议但不能提交的提交。我们不会在这里进一步详细说明 go,所以我们可以把它留在“建议的下一次提交”。)

When you do run git commit , Git simply packages up whatever is in the index at that time .当您运行git commit时,Git 只是打包当时索引中的任何内容 If you forget to git add a modified file, Git will commit whatever is in the index under that name—if anything—because what's in the index is still the old version of the file.如果您忘记git add修改后的文件,Git 将提交该名称下索引中的任何内容(如果有的话),因为索引中的内容仍然是该文件的旧版本 And, if you don't git add a file on purpose, the same thing happens.而且,如果您git add文件,也会发生同样的事情。

It's hard to see what's in the index directly, but it's easy to compare what's in the index to other things:很难直接看到索引中的内容,但很容易将索引中的内容与其他内容进行比较

  • git diff --cached compares what's in the current commit to what's in the index right now . git diff --cached当前提交中的内容与索引中的内容进行比较。 You can use git diff --staged as a synonym, if you like the term staging area better (it is a better term than cache ).您可以使用git diff --staged作为同义词,如果您更喜欢暂存区域这个术语(它缓存更好)。

    Hence, if something doesn't show up as different here, the index copy of the file matches the committed copy of the file.因此,如果此处没有显示出不同之处,则文件的索引副本与文件的已提交副本相匹配。

  • git diff compares what's in the index right now to what's in the working tree right now . git diff将索引的内容与工作树中的内容进行比较。 That is, if something shows up here, the index copy of the file doesn't match the working tree copy.也就是说,如果此处出现某些内容,则文件的索引副本与工作树副本不匹配 The diff shows you what's different.差异向您展示了不同之处。

  • The git status command runs both of these two git diff commands for you, but with --name-status so as to not show the actual changes . git status命令为您运行这两个git diff命令,但使用--name-status以便不显示实际更改 Instead, the first diff— HEAD -vs-index—tells you what files if any would be different if you committed right now.相反,第一个差异 — HEAD -vs-index — 告诉您如果您现在提交,哪些文件(如果有的话)会有所不同。 The status command calls these files staged for commit . status 命令调用这些文件staged for commit The second diff, index-vs-working-tree, tells you what files you could git add if you wanted;第二个差异是 index-vs-working-tree,它告诉您git add如果需要,可以添加哪些文件; the status command calls these files not staged for commit . status 命令调用这些未暂存提交的文件。

Pull requests拉取请求

Pull requests are, unfortunately, a little bit complicated.不幸的是,拉取请求有点复杂。 To understand them properly, we need to realize that Git commits have to be passed around .要正确理解它们,我们需要意识到必须传递Git 次提交。

Suppose you have, in your Git repository, the following chain of commits:假设您在 Git 存储库中有以下提交链:

...--F--G--H   <-- main
            \
             I--J   <-- feature (HEAD)

But your Git repository is a clone of some other Git repository, perhaps over on GitHub. Their repository has commits—which you got from them—and branch names.但是您的Git 存储库是其他一些 Git 存储库的克隆,可能在 GitHub 之上。他们的存储库具有提交(您从他们那里获得)和分支名称。

Your Git doesn't use their Git's branch names.你的 Git 没有使用他们的 Git分支名称。 Your Git takes their Git's branch names and renames them .你的 Git 取了他们的 Git 分支名称并重命名 That's because your branch names are yours , as your Git moves them around by adding new commits.那是因为你的分支名称是的,因为你的 Git 通过添加新提交来移动它们。 We cannot (and don't want to) move their names around while we add our own commits, after all.毕竟,我们不能(也不想)在添加自己的提交时移动他们的名字。 So, if your Git—by "your Git" I mean your Git software, running on your laptop for instance, using your repository—has commit H as your latest main -branch commit, and their Git (their software with their repository, over on GitHub) has commit H as their latest main -branch commit, your own repository will actually have this:所以,如果你的 Git——我说的“你的 Git”是指你的 Git 软件,例如在你的笔记本电脑上运行,使用你的存储库——提交H作为你最新的main分支提交,并且他们的Git(他们的软件和他们的存储库,超过在 GitHub 上)将提交H作为他们最新的main分支提交,你自己的存储库实际上会有这个:

...--F--G--H   <-- main, origin/main
            \
             I--J   <-- feature (HEAD)

The name origin/main is a remote-tracking name .名称origin/main是一个远程跟踪名称 It just remembers where their branch name points.它只记得他们的分支名称指向的位置。 Your Git will update this whenever your Git gets updates from their Git.只要您的 Git 从他们的 Git 获得更新,您的 Git 就会更新此信息。

Now, if you made commits I and J yourself, and you run:现在,如果您自己提交IJ ,然后运行:

git push origin feature

your Git will call up their Git and tell them the hash ID for commit J .您的 Git 将调用他们的 Git 并告诉他们提交J的 hash ID。 They'll look in their repository and find that they don't have this commit (because you made it).他们会查看他们的存储库并发现他们没有这个提交(因为你做了)。 Your Git is now obligated to offer them commit I too;您的 Git 现在有义务向他们提供 commit I too; they won't have that one and will ask for it.他们不会有那个并且会要求它。 Your Git must now offer them commit H , but this time they do have the commit, so they'll say no thanks, I have that one already .你的 Git 现在必须向他们提供提交H ,但这次他们确实有提交,所以他们会说不,谢谢,我已经有那个了 This enables your Git to stop offering commits, because the fact that they have H means they also have every earlier commit .这使您的 Git 能够停止提供提交,因为他们有H的事实意味着他们也有每个更早的提交

Your Git now packages up I and J and any files and other supporting objects needed for these new commits and sends them over.您的 Git 现在打包IJ以及这些新提交所需任何文件和其他支持对象,并将它们发送过来。 Then your Git will ask their Git to create or update a branch name feature in their repository.然后你的 Git 会要求他们的 Git 在他们的存储库中创建或更新分支名称feature If that goes well, they now have the name feature selecting commit J —which you and they now share —and that looks like this in your repository:如果一切顺利,他们现在拥有选择提交J的名称feature ——你和他们现在共享——在你的存储库中看起来像这样:

...--F--G--H   <-- main, origin/main
            \
             I--J   <-- feature (HEAD), origin/feature

In their repository, they only have (their) main pointing to H , and (their) feature pointing to J : they don't have these special remote-tracking names that your Git uses;他们的存储库中,他们只有(他们的) main指向H和(他们的) feature指向J :他们没有您的 Git 使用的这些特殊的远程跟踪名称; your git push has them set their branch names directly.您的git push让他们直接设置分支名称。 Hence, sometimes they'll refuse a push, perhaps because they already have that branch name, and they're using it to remember some other important commit hash ID.因此,有时他们会拒绝推送,也许是因为他们已经有了该分支名称,并且他们正在使用它来记住其他一些重要的提交 hash ID。

Anyway, assuming they do accept this push, you can now, over on GitHub, generate a pull request using their branch name feature .无论如何,假设他们确实接受了这个推送,你现在可以在 GitHub 上使用他们的分支名称feature生成一个拉取请求 That will ask someone to look over these new commits and, if they (the someone) like them, incorporate those new commits into their branch(es) somehow.这将要求某人查看这些新提交,如果他们(某人)喜欢它们,则以某种方式将这些新提交合并到他们的分支中。 We'll ignore, for now, the how and all the possible consequences, as these get very complicated.现在,我们将忽略所有可能的后果,因为这些会变得非常复杂。

What if you put files into your commits that you should not have?如果您将不应该拥有的文件放入您的提交中怎么办?

Suppose that, in commits I and/or J , you updated some file you didn't mean to update.假设在提交I和/或J中,您更新了一些您不想更新的文件。

You literally can't take this back.你真的不能收回这个。 Commits I and J are stuck the way they are, forever.提交IJ永远保持原样。 But you don't need to.但你不需要。 Just make a new branch name that points to commit H and get on it:只需创建一个指向提交H的新分支名称并继续:

...--F--G--H   <-- main, origin/main, refeature (HEAD)
            \
             I--J   <-- feature, origin/feature

Now use Git's facilities, such as git cherry-pick -n , to grab updates from commit I but not commit them yet .现在使用 Git 的工具,例如git cherry-pick -n ,从提交I中获取更新但尚未提交 Then use the git restore command to put the index version of the file or files back, and make a new commit with git commit :然后使用git restore命令将一个或多个文件的索引版本放回原处,并使用git commit进行新的提交:

             K   <-- refeature (HEAD)
            /
...--F--G--H   <-- main, origin/main
            \
             I--J   <-- feature, origin/feature

Repeat with commit J as appropriate:根据需要重复提交J

             K--L   <-- refeature (HEAD)
            /
...--F--G--H   <-- main, origin/main
            \
             I--J   <-- feature, origin/feature

Close the bad pull request, have GitHub delete their feature ( git push origin --delete feature ), and push refeature and make a new pull request.关闭错误的拉取请求,让 GitHub 删除他们的featurerefeature git push origin --delete feature ),然后推送重新功能并发出新的拉取请求。 Decide whether or not to keep your own feature branch;决定是否保留自己的feature分支; rename it if you like;如果你愿意,重命名它; do whatever you want with it.用它做任何你想做的事。 It's your branch, not anyone else's.这是你的分支,不是别人的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM