使用Git时如何使生活更轻松(以及用于深度浸泡的多种材料)


超现实主义吉他手的龙之树II

对于每天使用Git但感到不安全的人,团队Mail.ru Cloud Solutions翻译了前端开发人员Shane Hudson的文章在这里,您会发现一些技巧和窍门,可以使使用Git变得更容易一些,以及一些更高级的文章和手册。

Git出现在大约15年前。在这段时间里,他从弱者变成了无敌的冠军。今天,新项目通常是从团队开始的git init无疑,这是我们许多人日常使用的重要工具,但通常它类似于魔术-明亮但危险。

关于Habr的文章很多,关于Git的入门,Git的工作原理以及最佳分支策略的描述。在这里,作者集中于如何简化Git的工作。

我们把事情整理好


Git的目的是保存您的工作,切换上下文-并执行其他操作。这可以是代码的备份,也可以是异步开发几种不同功能的能力。仅因为在第一个版本中发现错误而放弃第二个版本会很糟糕。以v1_final_bug_fixed之类的名称保存文件也同样令人尴尬。如您所知,这将导致一团糟。

我们都知道,当我们的更新整齐地放在可以与同事共享的Git分支上时,生活会变得更加轻松。但是,当您更改上下文然后返回时,通常会出现这种情况-并且找不到正确的分支。根本有提交吗?也许他是隐藏的?也许提交没有通过,现在每个人都去了错误的分支,而且一切都不好,我正在做非常糟糕的工作!是的,每个人都在那里,并感到了这种怀疑。有一些方法可以处理这种情况。

按日期对分支进行排序


按日期排序显示从上一个开始的所有本地分支机构。很平常的事,但是它对我有很多帮助:

# To sort branches by commit date
git branch --sort=-committerdate

上一个线程


如果您没有提交,请切换分支,然后又想返回上一个分支,该怎么办?如果您对它的名称有所了解,可以在分支列表中找到它。但是,如果它不是分支而是detached HEAD特定的提交怎么办?

事实证明,有一个简单的出路:

# Checkout previous branch
git checkout -

运算符-是语法的简写@{-1},可让您切换回任意数量的结帐。因此,例如,如果您创建了一个branch feature/thing-a,然后,然后是feature/thing-b,则bugfix/thing-c该参数@{-2}将使您返回feature/thing-a

# Checkout branch N number of checkouts ago
git checkout @{-N}

显示有关所有分支的信息


该标志v显示所有分支的列表以及最后的提交标识符和消息。双击vv还将显示远程上游分支,然后是本地分支:

# List branches along with commit ID, commit message and remote
git branch -vv

查找文件


我们都陷入了这种情况:不知何故,一个文件留在了错误的分支中。该怎么办?重做所有工作或将代码从一个分支复制到另一个分支?不,幸运的是,有一种方法可以找到特定文件。

考虑到git checkout -将您带到上一个分支,该方法有些奇怪通常,如果您--在签出后在分支名称之后指定,这将允许您指定要查找的特定文件。如果没有提示,您不会猜到这样的功能,但是如果您知道,这将非常方便:

git checkout feature/my-other-branch -- thefile.txt

清除状态


托马斯·拉科马(Tomasz Lacoma)在推文中表示git status,借助旗帜来减少发行量-sb并补充说:“多年来,我一直在使用Git,但没有人告诉我这一点。” 这不仅仅是寻找丢失的文件。有时简化问题可以使查看更改更容易。

大多数Git命令都有这些标志,因此您应该学习如何使用它们来自定义工作流程:

# Usually we would use git status to check what files have changed
git status

# Outputs:
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)

modified: README.md

Untracked files:
(use "git add <file>..." to include in what will be committed)

another-file
my-new-file

# Using the flags -sb we can shorten the output
git status -sb

# Outputs:
## master
M README.md
?? another-file
?? my-new-file

整个故事


有时候,有些事情完全出错了,例如,您在提交之前不小心放弃了已进行的(准备)更改。如果git log不允许您返回到先前的状态,并且上述提示均无帮助,那就是git reflog

您在Git中通过引用更改内容的所有操作HEAD@{}(例如push/pull/branch/checkout/commit)都属于reflog(引用日志)。实际上,这就是您所有动作的故事,无论您身在哪个分支。这是与的区别git log,后者显示了特定分支的更改。


您可以git show使用提交ID-并查看特定的更改。如果这是您想要的,它将git checkout把您转移到所需的分支,甚至允许您选择一个特定的文件,如上所示:

# See the reference log of your activity
git reflog --all

# Look at the HEAD at given point from reflog
git show HEAD@{2}

# Checkout the HEAD, to get back to that point
git checkout HEAD@{2}

准备错过提交的文件


在极端情况下,如果这git reflog不帮助找回文件(例如,对中间文件进行了硬重置),则还有另外一个技巧。

每次更改都存储在.git/objects活动项目中充满文件的对象内部,因此几乎不可能找出来。但是,有一个名为的Git命令git fsck,该命令用于检查存储库中的完整性(损坏的文件是否存在)。我们可以将其与标志--lost-found一起使用,以搜索与提交无关的所有文件。这样的文件称为“悬空斑点”。

此命令还允许您查找“悬挂的树”和“悬挂的提交”。如果需要,可以使用flag --dangling,但是优点--lost-found它将所有相关文件提取到一个文件夹中.git/lost-found最有可能的是,在一个活动项目中,您将有许多这样的“挂起”文件。Git有一个垃圾处理命令,该命令会定期运行并删除它们。

因此,它将--lost-found显示所有文件以及创建的时间/日期,从而极大地方便了搜索。请注意,每个单独的文件仍将是单独的,也就是说,您不能使用签出。另外,所有文件都将具有难以理解的名称(哈希),因此您必须将必要的文件复制到另一个位置:

# This will find any change that was staged but is not attached to the git tree
git fsck --lost-found

# See the dates of the files
ls -lah .git/lost-found/other/

# Copy the relevant files to where you want them, for example:
cp .git/lost-found/other/73f60804ac20d5e417783a324517eba600976d30 index.html

团队合作中的Git


单独使用Git是一回事,但是当您与一群通常具有完全不同的经验,技能和工具的团队一起工作时,Git既是福也是祸。这是共享相同代码库,进行代码审查并监视整个团队进度的强大工具。同时,要求所有员工对如何在团队合作中使用它有共同的了解。无论是什么意思:命名分支的惯例,在提交中格式化附带的消息或选择要在提交中包括哪些文件,确保良好的沟通并就如何使用此工具达成共识非常重要。

确保初学者入门的简便性,并考虑如果初学者在不了解公司采用的原则和约定的情况下开始提交内容,将会发生什么,这一点始终很重要。这不是世界末日,但可能会引起一些混乱,并需要一些时间才能返回到协调的方法。

本节包含有关如何将接受的协议直接集成到存储库本身,自动化和发出声明中最大任务数的一些建议。在理想情况下,任何新员工几乎都会立即以与团队其他成员相同的风格开始工作。

同一行的结尾


默认情况下,Windows使用DOS行尾\r\n(CRLF),而Mac和Linux使用UNIX行尾\n(LF),而旧版本的Mac使用\r(CR)。因此,随着团队的成长,更可能出现行尾不兼容的问题。这很不方便,它们(通常)不会破坏代码,但是由于它们,提交和池请求显示了各种不相关的更改。通常,人们只是无视它们,因为走来走去并更改所有错误的行尾非常麻烦。

有一个解决方案-您可以要求所有团队成员配置其本地配置以自动完成生产线:

# This will let you configure line-endings on an individual basis
git config core.eol lf
git config core.autocrlf input

当然,您需要注册此约定和一个初学者,这很容易忘记。如何为整个团队做到这一点?根据操作算法,Git会检查.git / config存储库中是否存在配置文件,然后检查中的用户的系统范围配置~/.gitconfig,然后检查中的全局配置/etc/gitconfig

所有这些都很好,但是事实证明,这些配置文件都无法通过存储库本身安装。您可以添加特定于存储库的配置,但它们不会扩展到其他团队成员。

但是,实际上有一个文件提交到存储库。它称为.gitattributes。默认情况下,您没有该文件,因此请创建一个新文件并将其另存为*.gitattributes*它为每个文件设置属性。例如,您可以强制git diff使用图像文件中的exif标头,而不是尝试计算二进制文件中的差异。在这种情况下,我们可以使用通配符,以便该设置适用于所有文件,实际上,它充当整个命令的通用配置文件:

# Adding this to your .gitattributes file will make it so all files
# are checked in using UNIX line endings while letting anyone on the team
# edit files using their local operating system’s default line endings.
* text=auto

自动隐藏


通常将已编译的文件(例如node_modules/添加到.gitignore,以便将它们存储在本地而不上传到存储库。但是,有时您仍然想上传文件,但是不想以后每次在池请求中都满足文件要求。

在这种情况下(至少在GitHub上),您可以将标记的路径添加到.gitattributes linguist-generated并确保.gitattributes在存储库的根文件夹中。这将在池请求中隐藏文件。它们将被“最小化”:您仍然可以看到更改的事实,但是没有完整的代码。

减少代码审查过程中压力和认知负担的所有事情都可以提高其质量并减少时间。

例如,您想将资源文件(资产)添加到资源库,但以后将不对其进行修改和跟踪,因此可以将以下行添加到具有属性的文件中:

*.asset linguist-generated

经常使用git blame


哈里·罗伯茨 Harry Roberts )的文章“我喜欢用Git做的小事”建议git blame(分配git praise翻译)分配一个别名(翻译成“英语”),以使该团队感到积极。当然,重命名不会改变团队的行为。但是,每当讨论使用功能时git blame,每个人都会感到紧张,我当然也是如此。将责备(罪责)一词视为否定是很自然的事情……但这是完全错误的!

一个强大的功能git blame (或者git praise,如果需要的话)显示谁是最后使用此代码的人。我们不会责怪或称赞他,而只是想澄清情况。可以清楚地询问哪些问题以及向谁提问,从而节省了时间。

它不仅应该表现git blame为一件好事,而且应该作为一种沟通手段,帮助整个团队减少混乱,而不是浪费时间弄清楚谁知道什么。某些IDE(例如Visual Studio)将此功能激活为注释。对于每个功能,您都会立即看到谁最后一次更改了它(因此可以与谁讨论)。

丢失文件的模拟git怪


最近,我看到我们团队中的一位开发人员试图弄清楚谁删除了文件,何时以及为什么。看来这里可以提供帮助git blame,但是它可以处理文件中的行,并且如果文件丢失则没有用。

但是,还有另一种解决方案。老忠实git log如果您查看不带参数的日志,则会看到当前分支中所有更改的一长串列表。您可以添加一个提交标识符以查看此特定提交的日志,但是如果您指定了--(我们先前使用它来定位特定文件),则可以获得该文件的日志-甚至不再存在:

# By using -- for a specific file,
# git log can find logs for files that were deleted in past commits
git log -- missing_file.txt

提交消息模板


提交消息通常需要改进。团队中的开发人员迟早会得出这个结论。有很多改进方法。例如,您可以从内部项目管理工具中引用错误标识符,或者鼓励写至少一些文本而不是空白消息。

每次有人克隆存储库时,都需要手动运行此命令,因为配置文件未提交到存储库。但是,这很方便,因为您可以使用可以用作提交消息模板的任何名称来创建公共文件:

# This sets the commit template to the file given,
# this needs to be run for each contributor to the repository.
git config commit.template ./template-file

Git自动化


Git是功能强大的自动化工具。这并不是立即显而易见的,但请您自己想一想:他看到了您在存储库中的所有活动以及其他参与者的活动,并且他掌握了许多非常有用的信息。

吊钩


通常,您会看到团队成员在工作时执行重复性任务。这可以是在将分支发送到服务器之前(发送之前挂钩)通过测试和linter的测试,也可以是强制命名分支的策略(提交之前挂钩)。关于此主题,Konstantinos Lamonis在Smashing杂志上发表了一篇文章,标题为“如何使用Git挂钩简化工作流程

手动自动化


git bisect是Git中的关键自动化功能之一。许多人听说过它,但很少有人使用它。最重要的是处理Git树(提交历史记录)并查找输入错误的位置。

最简单的方法是手工操作。首先git bisect start,设置好提交和坏提交的标识符(没有错误且有错误的地方),然后执行git bisect goodgit bisect bad为每个提交执行。

这是一个比乍看之下更强大的功能,因为它不会线性运行Git日志,这可以作为迭代过程手动完成。相反,它使用二进制搜索来有效地以最少的步骤数执行提交:

# Begin the bisect
git bisect start

# Tell git which commit does not have the bug
git bisect good c5ba734

# Tell git which commit does have the bug
git bisect bad 6c093f4

# Here, do your test for the bug.
# This could be running a script, doing a journey on a website, unit test etc.

# If the current commit has bug:
git bisect bad

# If the current commit does not have the bug
git bisect good

# This will repeat until it finds the first commit with the bug
# To exit the bisect, either:

# Go back to original branch:
git bisect reset

# Or stick with current HEAD
git bisect reset HEAD

# Or you can exit the bisect at a specific commit
git bisect reset <commit ID>

前进:科学自动化


Stuart Halloway在科学的调试报告中解释了如何使用该命令git bisect自动进行调试。
他专注于Clojure,但我们无需了解这种语言即可从他的演讲中受益。

Git bisect部分是科学自动化。您编写了一个可以测试某些东西的小程序,Git来回跳转,每次跳转都将世界减半,直到找到测试更改状态的边界。
斯图尔特·哈洛韦(Stuart Halloway)

git bisect乍一看,可能看起来像是一个有趣且非常酷的功能,但最后它并不是很有用。斯图尔特的表现在很大程度上表明,像过去一样,调试实际上适得其反。相反,如果您专注于经验事实(无论测试是否通过),则可以对所有提交(从工作版本开始)运行它,并减少我们习惯的“在黑暗中徘徊”的感觉。

那么我们如何实现自动化git bisect您可以为每个相应的提交传递脚本。之前,我说过您可以在bisect的每个步骤中手动运行脚本,但是如果传递命令来运行,它将在每个步骤中自动运行脚本。它可以是专门用于调试此特定问题或测试(脚本,功能,集成,任何类型的测试)的脚本。因此,您可以编写测试以验证回归不重复,并在以前的提交上运行此测试:

# Begin the bisect
git bisect start

# Tell git which commit does not have the bug
git bisect good c5ba734

# Tell git which commit does have the bug
git bisect bad 6c093f4

# Tell git to run a specific script on each commit
# For example you could run a specific script:
git bisect run ./test-bug

# Or use a test runner
git bisect run jest

过去的每一次提交


优势之一git bisect是有效地使用二进制搜索以非线性方式绕过历史中的所有事件。但是有时需要线性旁路。您可以编写一个脚本来读取Git日志,并在每次提交时循环遍历代码。但是有一个朋友会为您做到这一点:git rebase

卡姆兰·艾哈迈德(Kamran Ahmed)在按原样编写的一条推文rebase中,提交没有通过测试:

查找未通过测试的提交:

$ git rebase -i --exec "yarn test" d294ae9

该命令对d294ae9和HEAD之间的所有提交运行yarn test,并在测试崩溃的提交处停止。

我们已经考虑git bisect过这项任务,它可能会更有效率,但是在这种情况下,我们不仅限于一个用例。

有创造力的地方。也许您想生成有关代码随时间变化的报告(或显示测试历史记录),仅解析Git日志是不够的。也许这不是本文中最有用的技巧,但它很有趣并显示了一项任务,而我们之前从未相信过这一现实:

# This will run for every commit between current and the given commit ID
git rebase -i --exec ./my-script

一系列文章和手册可帮助您更深入地了解Git


在这样的文章中,不可能深入探讨该主题,否则整本书都会出现。我选择了一些小技巧,即使是经验丰富的用户也可能不知道。但是Git具有更多功能:从基本功能到复杂脚本,精确的配置和控制台集成。因此,以下是您可能感兴趣的一些资源:

  1. 资源管理器git一个交互式站点,可以帮助您轻松地了解如何实现所需的目标。
  2. 混蛋吧!我们每个人都可能在Git中迷失方向,不知道如何解决任何问题。该站点提供了许多最常见问题的解决方案。
  3. 临git这本免费书籍是了解Git的宝贵资源。
  4. Git Docs. — . , Git Docs, Git (, man git-commit) Git .
  5. Thoughtbot. Git Thoughtbot .
  6. Git. Git.
  7. Git. , … . Git, .
  8. Git:从入门到高级MikeRitmüller撰写了这篇有用的文章,非常适合新手Git用户。
  9. 我喜欢和Git做些小事哈里·罗伯茨(Harry Roberts)的这篇文章使我意识到,除了跨分支移动代码之外,Git还潜伏着许多可能性。
  10. Atlassian高级Git指南这些教程详细介绍了本文中提到的许多主题。
  11. Github上的Git备忘单为Git之类的工具准备好备忘单总是很方便的。
  12. 减少Git本文详细介绍了各种Git命令标志,并建议了许多别名。

但是你还能读什么

  1. Git. №1: , .git
  2. Git. №2: rebase.
  3. .

All Articles