使用 --patch git add --patch 升级你的 git 游戏

2025-06-10

使用 --patch 升级你的 git 游戏

git add --patch

我们都力求提交简洁、单一用途且有意义的提交信息。如果自上次提交以来进行了大量调试,这在实践中可能会很困难。我认识的许多人在开发和维护功能时都会使用git commit -Agit commit .。在进行小改动时,这没问题,但我通常不喜欢在提交超过一两行代码时使用这些选项。当我建议使用我最喜欢的 git add 选项时,很多人告诉我他们从未听说过或使用过它。

git add --patch

与其暂存所有最近的更改,不如git add --patch(或git add -p) 允许您将更改暂存到相关的块中。它会弹出一个交互式菜单,让您可以对暂存的更改进行精细控制。交互式界面最初会显示与输出相同的代码块git diff。当您在交互式菜单中看到每个更改时,您可以选择y暂存该块、n跳过该块或s将其拆分成更细粒度的部分。

例子

假设我正在开始一个新项目,并且我想要一个基本的用户类:

class User:
    """User class for my app"""

    def __init__(self, fist_name, last_name, role):
        self.first_name = fist_name
        self.last_name = last_name
        self.role = role

    def display_name(self):
        print("{} {}".format(self.fist_name, self.last_name))

    def display_role(self):
        print("User is a {}".format(self.role))
Enter fullscreen mode Exit fullscreen mode

在我提交此代码并返回后,我注意到有几件事我想改变。

首先,我意识到我多次将“first”拼写成了“fist”,这需要更正。其次,我意识到我不喜欢在我的类中将“role”设置为字符串变量。我更希望不同的用户角色是 User 的子类。所以我将文件修改成这样。

class User:
    """Base User class for my app"""

    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

    def display_name(self):
        print("{} {}".format(self.first_name, self.last_name))


class Admin(User):
    'Admin level user'

    def __init__(self, first_name, last_name, email):
        super(Admin, self).__init__(first_name, last_name)
        self.email = email


class Guest(User):
    'Guest user'

    def display_name(self):
        print("Guest {} {}".format(self.first_name, self.last_name))
Enter fullscreen mode Exit fullscreen mode

我想要记录两个独立的想法,所以我应该将这些更改保存在不同的提交中。git add -p即使这两个想法出现在同一个文件中,使用 也可以轻松实现。

当我输入时,git add -p我看到以下内容。

diff --git a/user.py b/user.py
index e0bb61a..1b59b32 100644
--- a/user.py
+++ b/user.py
@@ -1,13 +1,24 @@
class User:
-    """User class for my app"""
+    """Base User class for my app"""

-    def __init__(self, fist_name, last_name, role):
-        self.first_name = fist_name
+    def __init__(self, first_name, last_name):
+        self.first_name = first_name
         self.last_name = last_name
-        self.role = role

     def display_name(self):
-        print("{} {}".format(fist_name, last_name))
+        print("{} {}".format(self.first_name, self.last_name))

-    def display_role(self):
-        print "User is a {}".format(role)
+
+class Admin(User):
+   """Admin level user"""
+
+   def __init__(self, first_name, last_name, email):
+       super(Admin, self).__init__(first_name, last_name)
+       self.email = email
+
+
+class Guest(User):
+   """Guest user"""
+
+   def display_name(self):
+       print("Guest {} {}".format(self.first_name, self.last_name))
Stage this hunk [y,n,q,a,d,/,s,e,?]?
Enter fullscreen mode Exit fullscreen mode

由于我的user.py文件相对较短,所有内容都会显示在一个大块中。我可以通过选择此s选项将其分开。

Stage this hunk [y,n,q,a,d,/,s,e,?]? s
Split into 5 hunks.
@@ -1,3 +1,3 @@
class User:
-    """User class for my app"""
+    """Base User class for my app"""

Stage this hunk [y,n,q,a,d,/,j,J,g,e,?]? n
@@ -3,4 +3,4 @@

-    def __init__(self, fist_name, last_name, role):
-        self.first_name = fist_name
+    def __init__(self, first_name, last_name):
+        self.first_name = first_name
         self.last_name = last_name
Stage this hunk [y,n,q,a,d,/,K,j,J,g,e,?]? e
@@ -6,4 +6,3 @@
         self.last_name = last_name
-        self.role = role

     def display_name(self):
Stage this hunk [y,n,q,a,d,/,K,j,J,g,e,?]? n
@@ -8,4 +7,4 @@

     def display_name(self):
-        print("{} {}".format(fist_name, last_name))
+        print("{} {}".format(self.first_name, self.last_name))


Stage this hunk [y,n,q,a,d,/,K,j,J,g,e,?]? y
@@ -11,3 +10,15 @@

-    def display_role(self):
-        print("User is a {}".format(role))
+
+class Admin(User):
+   """Admin level user"""
+
+   def __init__(self, first_name, last_name, email):
+       super(Admin, self).__init__(first_name, last_name)
+       self.email = email
+
+
+class Guest(User):
+   """Guest user"""
+
+   def display_name(self):
+       print("Guest {} {}".format(self.first_name, self.last_name))

Stage this hunk [y,n,q,a,d,/,K,g,e,?]? n
Enter fullscreen mode Exit fullscreen mode
git commit -m "Fix typos: 'fist' -> 'first'"
[master f91e0eb] Fix typos: 'fist' -> 'first'
 1 file changed, 3 insertions(+), 3 deletions(-)
Enter fullscreen mode Exit fullscreen mode

通过将此文件的差异拆分为 5 个不同的块,我能够仅选择与修复fist->first拼写错误相关的更改,而不会影响代码的功能。

你可能会注意到一个棘手的问题:这个方法中有两个单独的修改,User.__init__()我不希望它们出现在同一个提交中。第一个修改是更正拼写错误。第二个修改是从函数声明中fist -> first删除参数。即使使用“hunk out”命令也无法解决这个问题,因为它们都在同一行。roles

你会注意到,我使用了选项,而不是yn。该选项会将你带入默认的终端编辑器(可能是 vim,除非你将其更改为其他编辑器),你可以在其中手动编辑文件以反映你想要暂存的更改。保存文件并退出,你就可以通过 看到已暂存并准备提交的更改seegit diff --cached

在这个例子中,我修改了这个块

-    def __init__(self, fist_name, last_name, role):
-        self.first_name = fist_name
+    def __init__(self, first_name, last_name):
+        self.first_name = first_name
Enter fullscreen mode Exit fullscreen mode

在提交之前看起来像这样

- def __init__(self, fist_name, last_name, role):
-     self.first_name = fist_name
+ def __init__(self, first_name, last_name, role):
+     self.first_name = first_name
Enter fullscreen mode Exit fullscreen mode

我可以使用git add -pagain 来查看下次提交的更改,或者也可以使用,git add user.py因为我知道我已经将所有剩余的更改暂存到了文件中。为了完成示例,我将使用git add -pagain。

diff --git a/user.py b/user.py
index 2a09e35..1b59b32 100644
--- a/user.py
+++ b/user.py
@@ -1,13 +1,24 @@
class User:
-    """User class for my app"""
+    """Base User class for my app"""

-     def __init__(self, first_name, last_name, role):
+     def __init__(self, first_name, last_name):
         self.first_name = first_name
         self.last_name = last_name
-        self.role = role

     def display_name(self):
         print("{} {}".format(self.first_name, self.last_name))

-    def display_role(self):
-        print("User is a {}".format(role))
+
+class Admin(User):
+   """Admin level user"""
+
+   def __init__(self, first_name, last_name, email):
+       super(Admin, self).__init__(first_name, last_name)
+       self.email = email
+
+
+class Guest(User):
+   """Guest user"""
+
+   def display_name(self):
+       print("Guest {} {}".format(self.first_name, self.last_name))
Stage this hunk [y,n,q,a,d,/,s,e,?]? y
Enter fullscreen mode Exit fullscreen mode
git commit -m "Break user roles out into different classes."
[master dea4c79] Break user roles out into different classes.
 1 file changed, 16 insertions(+), 5 deletions(-) 
Enter fullscreen mode Exit fullscreen mode

当我回顾我的代码时,git log我看到了两个独立而简洁的提交。如果我决定需要撤销将 拆分成User.roleAdmin类的提交Guest,我不会丢失拼写错误修复。

我使用此选项将所有更改暂存以备提交,即使只有一两行。它可以帮助我发现拼写错误。我再也不用担心拼写错误修复或 delinting 与重要的功能更改混在一起了。它还能帮助我将我的想法区分开来,即使这些想法是我同时开发的。

鏂囩珷鏉ユ簮锛�https://dev.to/thejessleigh/up-your-git-game-with---patch-5d33
PREV
🧠 新的 React 和旧的缓存 Rapscallion electro-react-ssr-caching 安装使用 React 服务器端渲染优化库 React 组件缓存 React 预渲染组件
NEXT
如何提高开发人员的生产力