当前位置: 首页 > 工具软件 > git-as-svn > 使用案例 >

git --git-dir_Git简介-第2轮(高级)

松琦
2023-12-01

git --git-dir

Git is an incredibly powerful, flexible, and capable distributed version control system. Unfortunately, it can also be off-putting and a bit terse in its documentation, something people have remarked about on a number of occasions.

Git是一个功能强大,灵活且功能强大的分布式版本控制系统。 不幸的是,它在文档中也可能令人反感且过于简洁,这是人们在许多场合提到的。

You may have already read the series Introduction to Git by Sean Hudgston. If not, I really suggest that you do. Not only is it a great introduction, as the name implies, but it’s also a good primer for this article.

您可能已经阅读了Sean Hudgston撰写的Git简介系列。 如果没有,我真的建议你这样做。 顾名思义,它不仅是一个很好的介绍,而且还是本文的不错入门。

Here I’ll discuss some advanced topics that you may or may not come across as a part of your normal development workflow – features that allow you to do more than other systems, such as SVN. These include:

在这里,我将讨论您可能会或可能不会在常规开发工作流程中遇到的一些高级主题,这些高级功能使您可以比其他系统(例如SVN)做更多的事情。 这些包括:

  • Exporting your repository

    导出存储库
  • Basic Rebasing

    基本基础
  • Reordering a set of commits

    重新排列一组提交
  • Splitting a set of commits

    拆分一组提交
  • Changing the commit message

    更改提交消息
  • Merging a set of commits

    合并一组提交

If you’ve spent your time exclusively with version control systems other than Git and worked by their philosophies, some of these concepts might be alien (or even taboo) to you. But don’t fear; I’ll explain how to perform such actions and show you times when they might be beneficial to use.

如果您仅将时间花在Git以外的版本控制系统上,并且按照他们的哲学工作,那么其中一些概念可能对您来说是陌生的(甚至是忌讳)。 但是不要害怕。 我将说明如何执行此类操作,并向您展示使用它们的有益时间。

导出存储库 (Exporting Your Repository)

Let’s start out nice and easy. Exporting may not be that advanced, but it’s a really handy feature. Exporting allows us to deliver a release or snapshot of our code to others without all of the version control information we normally keep.

让我们开始轻松愉快。 导出可能没有那么高级,但这是一个非常方便的功能。 导出使我们能够将代码的发布或快照交付给其他人,而无需我们通常保留的所有版本控制信息。

来自本地仓库的档案 (Archives from Local Repos)

Archiving can be a handy part of our deployment processes, with tools such as Phing and Capistrano, or continuous integration tools such as Hudson and Xinc. (Optionally, we could trigger this in response to a commit hook but perhaps that’s a bit excessive.)

使用诸如Phing和Capistrano之类的工具,或者诸如Hudson和Xinc之类的持续集成工具,归档可以成为部署过程中的便捷部分。 (可选地,我们可以响应提交钩子触发此操作,但这可能有点过分。)

The options for creating an archive from a local repository are pretty simple. Here’s an example:

从本地存储库创建档案的选项非常简单。 这是一个例子:

$ git archive --format=tar --prefix=sitepoint-git-advanced/ 
    HEAD > sitepoint-git-advanced.tar | 
    gzip > sitepoint-git-advanced.tar.gz

In the example above, I want the format of the archive to be TAR (you can also specify ZIP if you prefer). I’ve then specified a prefix value of “sitepoint-git-advanced”. If the trailing slash is not appended, then the name is given to all files in the archive. In this case, it’s only given to the entire archive.

在上面的示例中,我希望档案的格式为TAR(如果愿意,还可以指定ZIP)。 然后,我将前缀值指定为“ sitepoint-git-advanced”。 如果末尾未添加斜杠,则将为归档中的所有文件指定名称。 在这种情况下,仅将其提供给整个存档。

Now let’s look at another example, one in which the output is a ZIP file. Instead of specifying the format and then piping the output to gzip, we can use the --output parameter and provide a name with .zip as the file extension.

现在让我们看另一个示例,其中的输出是一个ZIP文件。 除了指定格式然后将输出传递到gzip ,我们可以使用--output参数并提供一个以.zip作为文件扩展名的名称。

$ git archive --output=sitepoint-git-advanced.zip  
    --prefix=sitepoint-git-advanced/ -9 HEAD

git archive exports the repository to a ZIP archive for us automatically instead of sending the result to stdout. When using ZIP, you can also specify the compression level using switches -0 to -9, which is handy if the resulting file would be rather large.

git archive自动将存储库导出到ZIP存档,而不是将结果发送到stdout。 使用ZIP时,还可以使用-0-9开关指定压缩级别,如果生成的文件会很大,这非常方便。

远程存储库中的档案 (Archives from Remote Repos)

Local repos aren’t the only type of repositories we can archive, though. With the --remote switch, we are able to archive repositories from Gitosis and other Git servers our team may be using to store collective code.

不过,本地存储库不是我们可以归档的唯一存储库类型。 使用--remote开关,我们可以从Gitosis和我们的团队可能用来存储集体代码的其他Git服务器中归档存储库。

The example below attempts to clone the Joind.In project. Unfortunately, to be honest, it doesn’t work (from searching forums I believe that it’s been deliberately disabled by Github to help them ensure a better user experience), but I’ve included it here to show you an example of the command.

下面的示例尝试克隆Joind.In项目。 不幸的是,老实说,它是行不通的(在搜索论坛中,我相信它已被Github故意禁用,以帮助他们确保更好的用户体验),但是我在此处提供了该示例,以向您展示该命令的示例。

$ git archive --remote=git://github.com/settermjd/joind.in.git 
    --format=tar --prefix=joind.in/ HEAD | 
    gzip > joindin.tar.gz

基本基础 (Basic Rebasing)

Now let’s get in to some of the more juicy aspects of working with Git. According to the Git SCM book, with the rebase command we can “take all the changes that were committed on one branch and replay them on another one.” In short, this allows us to merge branches and changes in a powerful and flexible way. It’s also here that a bit of a debate begins. If you’re familiar with other version control tools such as CVS, SVN, and Mercurial, then you may be used to a model where once a commit is made, that’s it – it can’t be changed. With Git, this isn’t necessarily the case.

现在,让我们进入使用Git的一些更有趣的方面。 根据Git SCM的书,使用rebase命令,我们可以“获取在一个分支上提交的所有更改,然后在另一个分支上重播它们。” 简而言之,这使我们能够以强大而灵活的方式合并分支和更改。 在这里也开始了一些辩论。 如果您熟悉其他版本控制工具,例如CVS,SVN和Mercurial,那么您可能会习惯于一旦做出提交即就无法更改的模型。 使用Git,不一定是这种情况。

重新排序提交 (Reordering Commits)

Suppose the order of our commits wasn’t quite what it should have been. We’ve made a set of commits, but it would be more practical going in a sequential order. Perhaps they all relate to the same code module and there’s a change for an unrelated module in the middle. It’s not a show stopper, but it might be helpful to have them together when reviewing the history months later.

假设我们提交的顺序与应有的顺序不符。 我们进行了一组提交,但按顺序进行将更为实用。 也许它们都与同一个代码模块相关,并且中间的一个不相关模块有所变化。 这不是秀场停止,但在几个月后回顾历史记录时将它们放在一起可能会有所帮助。

$ git rebase -i HEAD~5

Using the command above, I’ve started a rebase session covering the last five commits, displayed by git rebase in reverse order:

使用上面的命令,我已经启动了一个覆盖最后五个提交的rebase会话,由git rebase以相反的顺序显示:

pick da4fc8e changing default to add iteration
pick 003ab61 adding even iteration script
pick 701e132 reworking directory structure
pick c722b9f removing old files
pick 3a10e1c Added in files that were forgotten in the previous commit

Suppose commit 5 (3a10e1c) should be after commit 2 (003ab61). We can change the commit order in the editor as follows:

假设提交5(3a10e1c)应该在提交2(003ab61)之后。 我们可以在编辑器中更改提交顺序,如下所示:

pick da4fc8e changing default to add iteration
pick 003ab61 adding even iteration script
pick 3a10e1c Added in files that were forgotten in the previous commit
pick 701e132 reworking directory structure
pick c722b9f removing old files

Save the buffer and exit the editor and we receive the following:

保存缓冲区并退出编辑器,我们收到以下信息:

Successfully rebased and updated refs/heads/testing.

Running git log now produces the following output:

现在运行git log会产生以下输出:

commit ab97ffb2fe87c25ca48116ed03cdbe486dc0abb5
Author: Matthew Setter 
Date:   Fri Jan 18 12:54:00 2012 +0000

    removing old files

commit 3b5d6c5b0c6a866f426ff5bf412508ce9d9ae864
Author: Matthew Setter 
Date:   Fri Jan 18 12:53:30 2012 +0000

    reworking directory structure

commit d9ab87677f8e5692b649b650a6de6ce836c72531
Author: Matthew Setter 
Date:   Mon Jan 21 10:11:33 2012 +0100

    Added in files that were forgotten in the previous commit

commit 003ab6124b7f7a59be4fe152df28b9de706383ed
Author: Matthew Setter 
Date:   Fri Jan 18 12:44:08 2012 +0000

    adding even iteration script

We can see by the new commit order that the re-order was successful. Git rewound back to the first commit specified, then replayed the history with the changes we’ve just specified.

通过新的提交顺序,我们可以看到重新排序成功。 Git退回到指定的第一个提交,然后使用我们刚刚指定的更改重播历史记录。

更改提交消息 (Changing the Commit Message)

What if you’re used to writing commit messages in a particular way that, for example, you learned from a previous job, but now you’re at a new organization and they write them differently? You’ve just committed a change and the senior developer, upon reviewing it, sees the message and wants it changed to comply with the company standard. With Git, you can go back and change the message.

如果您习惯于以某种特定的方式(例如,您从上一份工作中学到了东西)来编写提交消息,但是现在您在一个新的组织中,他们以不同的方式编写它们,该怎么办? 您刚刚进行了更改,高级开发人员在查看了该更改后,看到了该消息,并希望对其进行更改以符合公司标准。 使用Git,您可以返回并更改消息。

First, we have to start the rebase process by issuing the following command:

首先,我们必须通过发出以下命令来启动变基过程:

$ git rebase -i HEAD~2

We’re requesting to rebase around two revisions prior to HEAD. The terminal displays the following in the editing buffer:

我们要求以HEAD之前的两个修订为基础。 终端在编辑缓冲区中显示以下内容:

pick c722b9f removing old files
pick bcc1dff adding some files

# Rebase 701e132..bcc1dff onto 701e132
#
# Commands:
#
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for ammending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like "squash" but discard the commit's log message
#  x, exec = run command (the rest of the line) using shell
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#

We see the two commits at the top. In the list of commands below that, we have the option for reword which allows us to change the commit message.

我们在顶部看到两个提交。 在下面的命令列表中,我们提供了reword选项,该选项可让我们更改提交消息。

Here I’ve changed pick to reword:

在这里,我将pick更改为reword

pick c722b9f removing old files
reword bcc1dff adding some files

# Rebase 701e132..bcc1dff onto 701e132
#
# Commands:
#
...

Saving and exiting the buffer will then allow us to re-specify the commit message.

保存并退出缓冲区将使我们能够重新指定提交消息。

合并一组提交 (Merging a Set of Commits)

You’re probably pretty diligent in your commit practices, ensuring commits only include a single change or a group of related changes for one purpose. But there’s always something that can upset our normal rhythm.

您可能对提交实践非常勤奋,确保提交仅出于一个目的包括一个更改或一组相关更改。 但是总有一些事情可以扰乱我们的正常节奏。

Let’s say we made a commit for a change, did some work and made another commit, and then did some further work and committed that. After the third commit, we discover that commits 1 and 3 really were related to the same update and should go together.

假设我们做出了更改的承诺,做了一些工作,又做了另一次提交,然后做了一些进一步的工作并做出了承诺。 第三次提交后,我们发现提交1和3确实与同一更新相关,应该一起使用。

If we were working with SVN or CVS, that would be it; the revision history would be fixed. With Git, we can open up the history and merge commits 1 and 3 into a single commit prior to commit 2. Let’s go through the process.

如果我们使用的是SVN或CVS,那就好了。 修订历史将是固定的。 使用Git,我们可以打开历史记录,然后将提交1和3合并到提交2之前的单个提交中。让我们完成整个过程。

We start off the rebase process looking at the last five commits which look as follows:

我们从查看最近的五次提交开始变基过程,如下所示:

$ git rebase -i HEAD~5

pick da4fc8e changing default to add iteration
pick 003ab61 adding even iteration script
pick d9ab876 Added in files that were forgotten in the previous commit
pick 3b5d6c5 reworking directory structure
pick ab97ffb removing old files

We then change the order so that 3 comes before 2 as follows:

然后,我们更改顺序,以使3排在2之前,如下所示:

pick da4fc8e changing default to add iteration
pick d9ab876 Added in files that were forgotten in the previous commit
pick 003ab61 adding even iteration script
pick 3b5d6c5 reworking directory structure
pick ab97ffb removing old files

We then change pick to squash on the new commit number 2:

然后,我们在新提交编号2上将压pick改为squash

pick da4fc8e changing default to add iteration
squash d9ab876 Added in files that were forgotten in the previous commit
pick 003ab61 adding even iteration script
pick 3b5d6c5 reworking directory structure
pick ab97ffb removing old files

We’re then put into editor mode again, showing us the previous commit messages. We add in a new commit message that summarizes the two commits before they’re merged together. So, I change the following:

然后,我们再次进入编辑器模式,向我们显示以前的提交消息。 我们添加了一条新的提交消息,该消息概述了两个合并在一起之前的提交。 因此,我更改以下内容:

# This is a combination of 2 commits.
# The first commit's message is: 

changing default to add iteration

# This is the 2nd commit message:

Added in files that were forgotten in the previous commit

With a new message:

带有新消息:

# This is a combination of 2 commits.
# The first commit's message is: 

Merging two changes together as they should be together.

After exiting the editor, the rebase process completes.

退出编辑器后,变基过程完成。

By starting, non-destructively, the rebase process again, we see that the two commits have been merged. We now have five commits, with the first being the one before the first one previously:

通过非破坏性地再次启动变基过程,我们看到两个提交已合并。 现在,我们有五个提交,第一个是之前的第一个提交:

pick f5cac8d adding top documentation
pick e50970f changing default to add iteration
pick 3c2b3a5 adding even iteration script
pick 3b136c1 reworking directory structure
pick 01ad46f removing old files

拆分一组提交 (Splitting a Set of Commits)

But what if we want to go in the opposite direction? What there’s a developer who’s young and maybe a bit careless, or what if you, yourself, have been a bit undisciplined? I know I suffer from this from time to time.

但是,如果我们想朝相反的方向怎么办? 有没有一个年轻但可能有点粗心的开发人员,或者如果您自己没有纪律,该怎么办? 我知道我不时遭受这种痛苦。

Let’s say that we have a commit with a number of changes that we’ve just thrown in because it’s late or we’re in a hurry. Now we’re fresh and want to fix up the mess. How do we do that?

假设我们有一个提交,其中包含一些更改,因为很晚或我们很忙,所以我们刚刚进行了更改。 现在我们很新鲜,想要解决问题。 我们该怎么做?

$ git commit -m "need to finish quickly"
[testing e6a98bb] need to finish quickly
 0 files changed
 create mode 100644 about.php
 create mode 100644 contact-us.php
 create mode 100644 default.php
 create mode 100644 login.php

In the example above, I’ve committed a set of files, three business module pages (about.php, contact-us.php and default.php) and a user module page (login.php). Let’s separate them and do things properly.

在上面的示例中,我提交了一组文件,三个业务模块页面( about.phpcontact-us.phpdefault.php )和一个用户模块页面( login.php )。 让我们将它们分开并正确地做事。

Starting rebase with the last 3 commits, we see the following:

从最近的3次提交开始重新设置基准,我们将看到以下内容:

pick 3b136c1 reworking directory structure
pick 01ad46f removing old files
pick e6a98bb need to finish quickly

Change pick to edit on the last commit (e6a98bb) and exit the editor to receive the following output:

更改pickedit的最后一次提交(e6a98bb),并退出编辑器,收到以下的输出:

Stopped at e6a98bb... need to finish quickly
You can amend the commit now, with

    git commit --amend

Once you are satisfied with your changes, run

    git rebase --continue

with git reset HEAD^ we rewind the commit, unstaging the files. Now we are able to commit them properly, adding the business and user pages in two separate commits.

使用git reset HEAD^我们回退提交,取消暂存文件。 现在,我们可以正确地提交它们,在两个单独的提交中添加业务和用户页面。

$ git add about.php contact-us.php default.php
$ git commit -m "Adding new business pages"
[detached HEAD a189c9b] Adding new business pages
 0 files changed
 create mode 100644 about.php
 create mode 100644 contact-us.php
 create mode 100644 default.php

$ git add login.php
$ git commit -m "adding new user login page"
[detached HEAD 9efcab9] adding new user login page
 0 files changed
 create mode 100644 login.php

Then, finish up by running git rebase with the --continue switch:

然后,使用--continue开关运行git rebase作为--continue

$ git rebase --continue
Successfully rebased and updated refs/heads/testing.

警告语 (A Word of Warning)

Now to quote the oft quoted phrase:

现在引用经常被引用的短语:

With Great Power comes Great Responsibility

拥有权利的同时也被赋予了重大的责任

Please remember that just because you can do something, doesn’t mean that you should. Especially if you’re collaborating in a team environment, if you make these changes in your repository and then merge with the master repository, you’re likely to, amongst other things, cause confusion with your team. It’s fine if it’s there valid reason and it doesn’t happen too often. But if it happens repeatedly, I’m sure you won’t be all that popular for too long.

请记住,仅仅因为您可以做某事,并不意味着您应该做。 尤其是在团队环境中进行协作时,如果在存储库中进行了这些更改,然后与主存储库合并,则很可能会引起团队混乱。 如果有正当的理由,并且不会经常发生,那很好。 但是,如果这种情况反复发生,我相信您不会在太长时间内受到所有用户的欢迎。

Also, you need to appreciate the potential conflicts that these types of changes may introduce into the code as well. While these features can be fun, interesting, and even exciting, be aware of the ramifications of what you’re doing.

同样,您需要了解这些类型的更改也可能会引入代码中的潜在冲突。 虽然这些功能可能很有趣,有趣甚至令人兴奋,但是请注意您正在做的事情的后果。

结论 (Conclusion)

I hope that after reading this article you see just how much power and flexibility Git provides, but yet that you also appreciate that with that power must also come an understanding of when and when not to apply it.

我希望阅读完本文后,您可以看到Git提供了多少功能和灵活性,但是您也希望通过此功能还必须了解何时以及何时不使用它。

Happy Git-time, and be share your thoughts and ideas in the comments so we can all benefit. For more information, here’s some links for further reading:

祝您在Git上度过愉快的时光,并在评论中分享您的想法和观点,以便我们都能从中受益。 有关更多信息,以下是一些链接,供您进一步阅读:

翻译自: https://www.sitepoint.com/introduction-to-advanced-git/

git --git-dir

 类似资料: