Git列出了自特定提交以来已修改(未添加)的所有文件,包括已添加和稍后修改的文件

时间:2014-04-26 12:55:28

标签: git powershell git-diff git-log

我最近开始研究一个拥有庞大代码库的项目。我决定创建一个本地git仓库来跟踪我的所有变化。而不是下载所有项目的现有文件并将它们添加到git。我只下载了我需要的那些。由于我需要更多文件,我下载了它们并将它们添加到git。

现在,客户希望我提供自特定提交以来我已更改的所有文件的列表。

git diff --diff-filter=M --name-only $last_deploy_commit_id

仅提供该提交中存在的已修改文件。

git diff --diff-filter=A --name-only $last_deploy_commit_id

列出自该提交以来添加的所有文件,但不会(稍后必须)修改。

git diff --diff-filter=AM --name-only $last_deploy_commit_id

列出自该提交以来添加或修改的所有文件。

我想要的是拥有

所有文件的列表
  • 要么已经存在,并且自提交以来已被修改
  • 或者,自那次提交以来,在该提交中都没有存在,之后被创建并被修改。

有办法做到这一点吗?我在Windows上,如果有帮助的话。如果需要,我可以使用一些基于PowerShell的脚本。

2 个答案:

答案 0 :(得分:1)

您可以将--name-status标记传递给git log,然后执行此操作 提交范围<commit>^..HEAD

$ git log --oneline 70f5c30^..HEAD --name-status
7f6aafa Add poopoo
A       poopoo.txt
1d961ae Add hello and goodbye
M       blar.txt
M       rawr.txt
0a1acf9 Add rawr
A       rawr.txt
70f5c30 Add blar moo and I'LL BE BACK!
M       README.md
A       blar.txt

提交范围<commit>^..HEAD使用 独占 起点, 意思是 它不包括在内 ,所以你必须使用 <commit><commit>^。请参阅Pro Git: Commit Ranges

注意: git logporcelain command,这意味着它不能保证在将来的Git版本中向后兼容。通常,如果要在脚本中使用Git命令的输出,则可以使用其中一个管道命令。但由于这似乎是一次性使用的事情,因此使用git log只需一次这个目的似乎是一个合理的解决方案。

过滤掉已添加但未修改的文件

获得上面的输出后,你可能会grep(或者不管怎样) 相当于grep的Windows PowerShell是包含MA和的行 对它们进行排序,然后筛选出A行,但没有行的文件名 M

我不想花时间学习足够的PowerShell来做到这一点, 但是,如果您使用的是Unix环境,可以在此处过滤结果 与Ruby:

$ git log --oneline <commit>^..HEAD --name-status | \
$ grep --extended-regexp "^(A|M)" | \
$ ruby ~/Desktop/stackoverflow-answer.rb

其中stackoverflow-answer.rb包含以下内容:

x = ARGF.map { |line| line.split("\t").map(&:chomp) }
        .each_with_object({}) do |parts, hash|
          if hash[parts.last]
            hash[parts.last] << parts.first
          else
            hash[parts.last] = [parts.first]
          end
        end
        .reject { |k,v| v.size == 1 && v.first == 'A' }
        .keys
puts x

答案 1 :(得分:0)

警告,Powsershell命令在已重命名的rootGit repo文件夹中不起作用。
使用Git 2.20(Q4 2018),Windows端口确定当前目录的方式一直是 改善了。

请参见commit 4745feeAnton Serbulov (skvoboo)(2018年10月23日)。
请参见commit 937974fJohannes Schindelin (dscho)(2018年10月23日)。
(由Junio C Hamano -- gitster --commit cc67487中合并,2018年10月30日)

  

mingw:在无法查询父目录时修复getcwd

     

GetLongPathName()函数在无法查询时可能会失败   确定长名称的路径组件的父目录   对于该组件。发生了,因为它使用了FindFirstFile()   对路径的每个下一个短部分起作用。 FindFirstFile()   需要List DirectorySynchronize的呼叫访问权限   过程。

     

在路径的某些部分缺少此类许可的情况下,   GetLongPathName()返回0作为结果,而GetLastError()返回   返回ERROR_ACCESS_DENIED

     

GetFinalPathNameByHandle()函数可以在这种情况下提供帮助,因为   它需要Read AttributesSynchronize所需的访问权限,   仅目标路径。

     

GetFinalPathNameByHandle()函数是在上引入的   Windows Server 2008/Windows Vista。因此,我们需要动态加载它。

在powershell会话中执行git log时会有所帮助:

  

mingw:确保getcwd()报告正确的情况

     

例如在PowerShell中切换当前工作目录时,很有可能使用与磁盘上记录的大写字母不同的大写字母。
  在cmd.exe中执行此操作可以神奇地调整大小写,但这在PowerShell中不会发生,因此getcwd()以不同于磁盘上记录的方式返回当前目录。

     

通常,除了您打电话时,这不会造成任何问题。

git log .
     

在名为“ GIT/”的子目录中,但是您已切换到“ Git/”,   您的getcwd()报告了后者,那么Git不会理解您想查看GIT/子目录中的历史记录,但是它认为您想查看目录中可能已经存在的某个目录的历史记录过去(但实际上从未如此)。