为什么要先 git add 才能 git commit amend

为什么要先 git add 才能 git commit_百度知道
为什么要先 git add 才能 git commit
进行 git stage:git reset hello, c,使用 git status,仅仅为了保持和以前的兼容做保留,每次递交之前;in-addition-to ‘git add’. I’m excited that staging files may soon be done via ‘git stage’ rather-than&#47.py://learn.2 分阶段递交比如. git diff ,并没有递交,跳过 git stage 这个命令。比如你修改了部分内容,其中 a。同时.py:///p/normal:git stage a,则需要再做一次 git stage ,此时工作区的文件不做任何修改,一个是进行快照:git stage 作为 git add 的一个同义词git diff --staged 作为 git diff --cached 的相同命令为了容易理解. reset 和 checkout的区别当文件加入了 stage 区以后, git diff --cached 是比较 stage 的文件的差异的,d. git 的 add .github,则只会对第一次的快照进行递交.html" target="_blank">http.html由于git这个特性.py,一个是分批,一个文件可能同时存在两种差异. 增加 stage 的带来的好处是什么,可以随时 checkout 回退递交之前://learn,需要确认是否已经将相关的修改都stage 了,想回退到stage的状态.com/p/normal. 最佳实践://learn.py,也是一个不直观的命令、分阶段递交,便于回退做了部分修改以后,后来又做了一些修改.事实上,后来你又做了一些修改.py d,请参见;2, 然后又做了一些修改,后面的修改.1 分批递交,降低commit的颗粒度比如。那么你就可以采用,容易引起混淆,是一个容易引起疑问的命令,直接递交6,git diff HEAD 仔细查看是否需要的递交git commit -a ://learn.py3:https。在 subversion 中的 svn add 动作是将某个文件加入版本控制,但是还不能做一次递交,就做了两个修改,如果直接采用 git commit 递交.py 做了一个快照.com/p/normal.html4:git checkout hello,然后就递交,当前内容还保存在 working 工作区.com/p/normal,你修改了 a.com/blog/196-gittogether-2008http。具体参见://github,也提到,推荐大家使用 git stage 和 git diff --staged 这两个命令.py属于另外一个功能相关修改, git diff --staged 和 git diff HEAD的差别当一个文件做了function 1&quot,才能递交。2:git checkout -- hello. 可以使用 git commit -a 命令。当文件加入了 stage 区以后?主要有两个好处.htmlthings like making use of the term ‘stage’ for things that happen in the index (such as using ‘git diff —staged’ instead of ‘git diff —cached’) is being worked on.pygit commit -m &quot,这时候,这时发现后面的修改有问题. This is nice for new users who often have a hard time seeing why you have to keep ‘git add’ing to stage /p/git stage b,如果要从stage删除.html" target="_blank">/p/normal。github 2008年的blog中://learn
其他类似问题
为您推荐:
commit的相关知识
其他1条回答
add是把修改加入到提交列表commit是本地提交。
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁为什么要先 git add 才能 git commit ?
为何不能默认之前被add的文件一定继续被加入?
按投票排序
1. git 的 add ,是一个容易引起疑问的命令。在 subversion 中的 svn add 动作是将某个文件加入版本控制,而 git add的意义完全不同。同时, git diff --cached 是比较 stage 的文件的差异的,也是一个不直观的命令。github 2008年的blog中,也提到,容易引起混淆:things like making use of the term ‘stage’ for things that happen in the index (such as using ‘git diff —staged’ instead of ‘git diff —cached’) is being worked on. I’m excited that staging files may soon be done via ‘git stage’ rather-than/in-addition-to ‘git add’. This is nice for new users who often have a hard time seeing why you have to keep ‘git add’ing to stage your changes.事实上,在 git 的后续版本中,就做了两个修改:git stage 作为 git add 的一个同义词git diff --staged 作为 git diff --cached 的相同命令为了容易理解,推荐大家使用 git stage 和 git diff --staged 这两个命令,而git add 和 git diff --cached 这两个命令,仅仅为了保持和以前的兼容做保留。2. 增加 stage 的带来的好处是什么?主要有两个好处,一个是分批、分阶段递交,一个是进行快照,便于回退2.1 分批递交,降低commit的颗粒度比如,你修改了 a.py, b.py, c.py, d.py,其中 a.py 和 c.py 是一个功能相关修改,b.py,d.py属于另外一个功能相关修改。那么你就可以采用:git stage a.py c.pygit commit -m "function 1"git stage b.py d.pygit commit -m "function 2"2.2 分阶段递交比如,你修改了文件 hello.py,修改了一些以后,做了 git stage heello.py动作,相当于对当前的hello.py 做了一个快照, 然后又做了一些修改,这时候,如果直接采用 git commit 递交,则只会对第一次的快照进行递交,当前内容还保存在 working 工作区。当前的最新修改,则需要再做一次 git stage ,才能递交。这中间细微的差别,请参见:由于git这个特性,需要注意到是,每次递交之前,需要确认是否已经将相关的修改都stage 了,否则可能仅仅递交了部分不完整的修改。比如你修改了部分内容,进行了 stage,后来你又做了一些修改,然后就递交,这时,后面的修改,并没有递交。2.3 文件快照,便于回退做了部分修改以后,进行 git stage,然后任何时刻,都可以回退到stage时的状态:git checkout -- hello.py3. git diff , git diff --staged 和 git diff HEAD的差别当一个文件做了stage,然后又做了一些修改,则:git diff 显示当前工作区的文件和stage区文件的差异git diff --staged 显示stage区和HEAD的文件的差异git diff HEAD 显示工作区和上次递交文件的差异具体参见 git help diff 的EXAMPLES部分。使用 git status 可以看到,一个文件可能同时存在两种差异。具体参见:4. reset 和 checkout的区别当文件加入了 stage 区以后,如果要从stage删除,则使用 reset,此时工作区的文件不做任何修改,比如:git reset hello.py这个命令就是 git stage hello.py 的反操作。当文件加入了 stage 区以后,后来又做了一些修改,这时发现后面的修改有问题,想回退到stage的状态,使用 checkout 命令:git checkout hello.py5. 可以使用 git commit -a 命令,跳过 git stage 这个命令,直接递交6. 最佳实践:做了阶段性修改,但是还不能做一次递交,这时先 git stage 一下如果有问题,可以随时 checkout 回退递交之前,使用 git status,git diff HEAD 仔细查看是否需要的递交git commit -a ,保证递交了所有内容
解答这个问题不应该看当前git的CLI,而是要看看git设计的源头。回头看看2005年的文章 ,里面有一句一直被git标榜的话:Git is not a source code management (SCM) system. It is, instead, a set of low-level utilities (Linus compares it to a special-purpose filesystem) which can be used to construct an SCM system.另外还需要对比一下和其他VCS的设计理念。早期的git操作都是直接操作tree的,update-cache,write-tree,commit-tree是当时设计的流程。git设计的时候分为object database和directory cache,前者目的上是希望持续存在的,后者只是临时的。也就是说,当时都是把要提交的change先放入cache,cache里有个不完整的tree,然后生成完整的tree病写入存储系统,再然后把tree绑定到commit上。之前的shell脚本就是这么写的,就是这个操作流程,类似于一个脚本只做一件事情。一个负责联系working directory和cache,一个负责联系cache和database。另外这样也很容易保证atomic operation,"pointer"-&commit-&tree-&cache每一步都可以很好的保证完成,即便产生了错误有了垃圾,可以通过git gc还有git fsck去补救。但是更为根本的是,据说(来源应该也是LWN,文章不记得哪篇了)Linus最初设计git时希望尽量绕开BitKeeper的影响,免得留下口实。于是git从一开始就抛弃了包括hg,fossil等VCS使用的manifest模式,也就是说不存在一个记录了本次commit所有items的manifest。基于这个理由,自然也没必要每次commit之前去扫描working directory去生成manifest,git将这个职责推给用户了。由于我个人喜欢存盘性质的高频commit,这样记录自己的开发轨迹,然后随后再rebase出一个squash的commit到公共的历史。所以我个人喜欢hg的模式了,每次改的都要提交,一次commit解决问题比较方便。
呃,,,,好像现有的答案还是没有到达那个关键点啊。当然,最直接的原因就是git发明了一个叫做暂存区的概念,但是为什么要发明这个概念呢?没有暂存区可以不?为什么一定要有暂存区,这才是真正的问题好吧。要解释这个问题,首先要回到GIT的前辈上来,SVN,集中式源代码管理工具的集大成者。我们知道SVN相较于第一代源代码管理工具如VSS、CVS有几个显著的区别,其中最重要的特性之一就是原子性提交,每一个提交都是由多个文件的修改组成,而且这个提交是原子性的,要么这些修改全部成功,要么全部失败。原子性提交带来的好处是显而易见的,这使得我们把项目整体还原到某个阶段或者时间点变得极为简便,就这一点SVN就完虐VSS等源代码管理工具。Git作为目前逼格最高的源代码管理工具,SVN这个优良的特性显然是要借鉴的。但是Linus马上发现了一个麻烦事儿,在命令行下面选择要提交的修改,还真TM是个麻烦事儿,因为用SVN的时候我们都是这么玩的:你妹啊,虽然GUI逼格相当的低,但是在这个场景下,可比命令行要方便得多了。这样一来,Git用户还能不能愉快的玩(zhuang)耍(bi)了?显然这点小问题完全难不倒Linus这么一位旷世奇才。我们只需要在commit前面,发明一个暂存区的概念就好了,这个暂存区是可以随意的将各种文件的修改放进去的,这样我们就可以用多个指令精确的挑选出我们需要提交的所有修改,然后再一次性的(原子性的)提交到版本库,问题就完美的解决了。而且,如果用户觉得这样实在是多此一举的话,可以自定义一个小脚本哦,,,,反正其实你们现在用的这些git命令,其实大部分都是一个批处理脚本哦。
解释的很清楚了。我列举一下svn是远远比不上的cache相关功能:1. `git add -p`同文件中添加特定hunk到cache中去2. `git diff --stat --cached`, commit前在review一下,确定提交了正确的文件3. `git diff --cached`,提交前review代码还有很多和cache相关的强大功能,比如reset等等。git给你更多的power和自由,不过如果你不喜欢的话,完全可以当成svn来用比如前面有人提到的`git -am`.
的回答基本是最切题的了。我这里再补充点更细节的。如果以文件为stage基本单位的话,那很多场合限制太多了,实际上不实用,但很多人可能不知道的是:git的stage对象实际是以hunk为单位。一个hunk就是一个diff中一段连续的改动,一个diff由一个或多个hunk所组成,而hunk的大小是可以控制的,最小单位是一行,也就是说你可以把diff一行一行的添加到stage中,然后分多次分别commit。这个功能有毛用?一个理想的开发过程是每个commit仅包含一个feature或bugfix。为什么要这样?当你需要bisect找bug时,或revert某个commit时,或cherry-pick某个commit到其它分支时……就会发现保持commit干净的重要性。(相信我,用到以上功能的机会绝对比你想象的要多的多的多)但不幸的是绝大多数人都有在一个commit中包含多项无关改动的倾向(包括我自己),至于为什么会这样,我也不知道,这里也不讨论,相信各位有开发经验的同学都会在现实中遇到无数这种实例,结果最后得到的通常是一串混乱不堪的历史。但git带来一个不一样的故事:它支持hunk。所以现在我工作时常见的一个典型场景是这样:1. 开始开发功能A2. 开发A的过程中发现有个小bug B,只需要改动几行就能搞定,于是顺手改掉3. 功能完成了,先把B所属的hunk stage起来,然后commit4. 再把剩余的跟A相关的所有hunk stage起来,然后commit最后得到一个干净的历史。如果放在hg之类的工具里,这真是一件相当麻烦的事。事实上我用了好多年hg,最后转到git上来一部分原因是因为github,另一部分就是为了stage+hunk。单纯从功能上来说hg有很多比git好用的地方,但加起来也不敌这一项。基于hunk的具体用法请见git add -p,但悲剧是这个内置的功能太不好用了,所以我基本上通过第三方工具来用。命令行的话强烈推荐tig这个基于curses的UI,vim的话就fugitive。其它GUI工具里我记得SourceTree好像也是支持的。------------补充个tig里的diff图,用蓝框标起来的区域就是独立的hunk了,tig中有个快捷键操作叫"stage-split-hunk",移动到某个hunk里按这个键就可以把它切分成更小单位,一直切下去最后就可以切成一行一行的。
参考《Pro Git》的《Git 对象》一章()可以知道Git用blob对象来存储文件内容,用tree对象存储目录里的文件名,用commit对象存储每一次提交。根据这个问题(),git add负责将文件内容存入blob对象,并更新index,git commit负责根据index生成tree对象,然后生成commit对象指向这个tree对象。关于索引参考《Git Community Book》的《Git索引》一章()。
Git比其他同类软件多出个暂存区域的概念,git add不是将文件置于版本控制之下,而是将文件添加到暂存区域(index)。所有新增的和修改过的文件都要执行git add命令添加后才能commit。commit时是不理会工作区的文件的,而是根据index为每个目录生成tree对象,然后再创建commit对象指向它。
这样做的好处是你可以通过git add -i命令()随意修改要加入暂存区域的文件。比如你一次修改了3个文件,要分成3个commit提交,那么每次添加一个文件到暂存区域然后commit就可以了。又或者,刚修改错了一个文件,可以从暂存区域里取出上次git add后的版本。
有一点要注意,git commit -a命令在文档里是这样描述的:
Tell the command to automatically stage files that have been modified and deleted, but new files you have not told git about are not affected.via
所以,新增加的文件不能通过git commit -a命令添加到暂存区域,还得单独运行git add命令。
实践是验证真理的一个标准。如果你在完成一个较大较复杂的功能,但是中途又想暂时将代码状态“暂存”起来,对就是“暂存”。有点类似于你挣了很多钱,但是又不方便一下存起来,如可能你想凑个整数(功能尚未开发完全)或者今天银行不开门(你当前连接不到服务器),怎么办?请一个管家帮你管理,你的钱富余了就给他,让他给你保管;如果你又要花钱,好,直接让他吐给你。最后,整数凑够了,而且银行开门了了,你说存到银行吧。当然,你要说你每天的收支在2位数以内(版本改动较小),又或者说你自己家就是银行(服务器在自己电脑上),得,还是别请管家了。
会问出这种问题,你的commit log一定写的不怎么样
它的add不是纳入管理跟踪,是从工作区加入到缓存区,然后commit,提交到仓库。它有三个区
个人理解,这么做是鼓励小步快跑式的开发。git的local cache(即index),提供了一种便利,让你可以保存当前的工作成果,进行下一步,直到最后你觉得可以提交了。在工作中大家应该经常遇到类似情形:已经有一些成果,但是还不完善,不能check in;你继续埋头苦干,结果不幸走岔路了;这个时候,想回到刚才状态,往往回不去或者很困难。如果有local cache,你就可以方便保存上一把的状态,随时恢复。当然,现在很多编辑工具也有类似功能,但像git这么方便的,据我所知是没有。另外,作为一个SCM,统一提供这种机制也是有好处的。坑就是你要特别小心index和真正本地文件的一致性,千万不要check in partial change。
已有帐号?
无法登录?
社交帐号登录}

我要回帖

更多关于 git add和commit 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信