查看未推送的 Git 提交

Posted

技术标签:

【中文标题】查看未推送的 Git 提交【英文标题】:Viewing unpushed Git commits 【发布时间】:2011-01-02 06:43:23 【问题描述】:

如何查看我所做的任何本地提交,但尚未推送到远程存储库?偶尔,git status 会打印出我的分支是在origin/master 之前提交的 X,但并非总是如此。

这是我安装 Git 的错误,还是我遗漏了什么?

【问题讨论】:

从 Git 2.5+(2015 年第二季度)开始,实际答案将是 git log @push..。在my answer below中查看新的快捷方式@push(引用您推送到的远程跟踪分支) @Torek - Git 使另一个简单的任务变得困难。每当一个 Git 问题以成百上千的点赞数和数百万的浏览量出现时,就会有人会想:哇,我们真的搞砸了这个工作流程。唉,Git 开发者在开发生命周期中省略了反馈步骤,因此没有纳入反馈。相反,他们一遍又一遍地犯同样的错误。对于这个问题,git status --all应该出现在2010年;或 git status -v 实际上应该提供包含额外信息的详细输出。 我不同意“git status -v”应该提供此信息,因为它旨在提供有关工作树的状态,因为它仅与签出的分支有关。但是,请参阅下面关于“git branch -v”的答案,我认为这应该是公认的答案 这个特定的 *** 问题的正确答案数量最多,但所有答案都没有任何意义。 @jww:我同意。在使用 mercurial 之后,我又回到了使用 git。与 mercurial 的易用性和优雅相比,git 是一团糟 【参考方案1】:
git log origin/master..HEAD

您也可以使用相同的语法查看差异

git diff origin/master..HEAD

【讨论】:

这是为我做的-出于某种原因 git log origin.. 本身就引发了错误。看起来我的本地分支的配置方式也有问题 - 一旦我在此处找到了更改:wincent.com/blog/… ...问题已解决,我可以再次使用 git status 来查看我想要的内容。 无价之宝:所以我做了git config --global alias.ahead "log origin/master..HEAD --oneline",这样我就可以快速找出我在哪里。更多糖果:for i in *; do echo $i && git ahead 2>/dev/null; done git log --stat origin/master..HEAD 带来一点额外的惊喜 这不是最好的解决方案。 Origin/master 可能并不总是上游分支。更好的解决方案是使用@u 而不是“origin/master”来指示上游分支。由于默认情况下暗示了 HEAD,因此也可以将其省略。请参阅@Ben Ling 的回答。传出更改:git log @u.. 传入更改:git log ..@u @Nocturne 我只想指出,当发布此答案时,@u 语法尚不可用,它仅在 February 12, 2010 上可用。此外,如果本地分支未配置上游,@u 将不起作用。最后,@u 目前不支持 tab 补全,<remote>/<branch> 带有 tab 补全仍然是获取此信息的最快方式之一,并且无论是否配置了上游,它都可以工作。【参考方案2】:

如果您想查看尚未推送的所有分支上的所有提交,您可能正在寻找类似这样的内容:

git log --branches --not --remotes

如果您只想查看每个分支上的最新提交以及分支名称,则:

git log --branches --not --remotes --simplify-by-decoration --decorate --oneline

【讨论】:

这太棒了。在一个相关场景中,我有两个本地分支和两个上游分支,并且一只本地手被合并到另一只手中。我想知道哪些提交可以安全地变基,但正常的git log master..HEAD 不起作用,因为有多个上游。这篇文章将我带到git log MyBranch --not --remotes,以在单个分支中显示所有尚未推送到任何上游的提交。 这非常有用,我在我的 zsh 配置中给它起了别名。谢谢。 我知道您的第二个命令也列出了尚未推送的提交,只是每个分支只显示一个。 --decorate 也显示了分支。 --graph 让它更加明显。 这是实际的解决方案。唯一一个不需要指定分支或需要定义上游的一般工作。【参考方案3】:

您可以显示您在本地但不是上游的所有提交

git log @u..

@u@upstream表示当前分支的上游分支(详见git rev-parse --helpgit help revisions)。

【讨论】:

在 Windows 上,我需要将最后一个参数括在引号中,例如: git log "@u.." git log @u.. -p 最有用的选项之一是-p,它显示了每次确认中引入的差异。 可能更好的 git log @push.. ,见 another answer. 我发现这个是最好的答案。我还发现,如果没有备忘单,我就无法在地球上记住它。为什么 git 开发人员没有选择明显的、符合 git status 的东西,因为我们想知道一个情况的 statusgit status -v 会更有意义。【参考方案4】:

这对我有用:

git cherry -v 

如Git: See all unpushed commits or commits that are not in another branch所示。

【讨论】:

我认为这应该是主要答案,因为它提供了更简洁的提交列表,而不是所有文件中难以阅读的冗长差异! git-cherry - “查找尚未应用于上游的提交”,似乎提供了 OP 的要求,但只有提交主题而不是整个提交消息。 值得注意的是,这只会告诉您当前签出的分支上是否有未推送的提交。它不会告诉您是否有未推送提交的本地分支(当前未签出)。【参考方案5】:

您可以使用git log

git log origin/master..

这假定 origin 是您的上游远程的名称,master 是您的上游分支的名称。在.. 之后省略任何修订名称意味着HEAD,它列出了尚未推送的新提交。

【讨论】:

每当我看到git log 和“2-dots-not-3”的答案时,它总是让我想起***.com/questions/53569/… ;) 只是将其添加到答案中 - 如果没有上游设置,此命令会导致说没有设置上游。如果您倾向于使用此命令查看暂存的提交,请运行 git branch --set-upstream master origin/<branch> 以设置上游。 这将与源中的默认分支进行比较,而不是当前的远程分支。 致命:不明确的参数'origin..':未知的修订或路径不在工作树中。 不,它显示了所有不同的最新提交,但不回答原始问题。【参考方案6】:

所有其他答案都在谈论“上游”(您从中提取的分支)。 但是本地分支可以推送到一个不同的分支,而不是它从中提取的分支。

master 可能不会推送到远程跟踪分支“origin/master”。master上游 分支可能是 origin/master,但它可以推送到远程跟踪分支 origin/xxx 甚至 anotherUpstreamRepo/yyy。 这些是由branch.*.pushremote 为当前分支以及global remote.pushDefault 值设置的。

那个远程跟踪分支在寻找未推送的提交时很重要:跟踪 本地分支 将被推送到的branch at the remote 的分支。branch at the remote 也可以是 origin/xxx 甚至是 anotherUpstreamRepo/yyy

Git 2.5+(2015 年第二季度)为此引入了一个新的快捷方式:<branch>@push

见commit 29bc885、commit 3dbe9db、commit adfe5d0、commit 48c5847、commit a1ad0eb、commit e291c75、commit 979cb24、commit 1ca41a1、commit 1ca41a1、commit 3a429d0、@9876543321、@、@9876543321 @、commit f052154、commit 9e3751d、commit ee2499f [均自 2015 年 5 月 21 日起] 和 commit e41bf35 [2015 年 5 月 1 日]Jeff King (peff)。(由@987654339 中的Junio C Hamano -- gitster -- 合并@,2015 年 6 月 5 日)

Commit adfe5d0 解释:

sha1_name:实现@push速记

在三角工作流中,每个分支可能有两个不同的兴趣点:您通常从中提取的@upstream,以及您通常推送到的目的地。后者没有简写,但有它很有用。

例如,您可能想知道哪些提交尚未 已推送

git log @push..

或者作为一个更复杂的示例,假设您通常从 origin/master(您将其设置为您的 @upstream)中提取更改,并将更改推送到您的 fork(例如,作为 myfork/topic)。 您可以从多台机器推送到您的 fork,这需要您从推送目的地而不是上游整合更改。 有了这个补丁,你可以这样做:

git rebase @push

而不是输入全名。

Commit 29bc885 补充:

for-each-ref:接受“%(push)”格式

就像我们有“%(upstream)”来报告每个引用的“@upstream”一样,这个补丁添加了“%(push)”来匹配“@push”。 它支持与上游相同的跟踪格式修饰符(因为您可能想知道,例如,哪些分支有要推送的提交)。

如果您想查看与您推送到的分支相比,您的本地分支领先/落后有多少提交:

git for-each-ref --format="%(refname:short) %(push:track)" refs/heads

【讨论】:

【参考方案7】:

我之前完成了一个提交,没有推送到任何分支,也没有远程或本地。只是提交。其他答案对我没有任何帮助,但是:

git reflog

在那里我找到了我的提交。

【讨论】:

如此链接git-scm.com/docs/git-reflog 中所述,引用日志或“reflogs”,记录本地存储库中何时更新分支和其他引用的提示。就我而言,我克隆了一个 repo,创建了一个新分支,删除了该分支,创建了一个新分支,创建了一个提交并更改了提交。所有这些步骤都记录为 HEAD@0: commit (amend) : .. HEAD@1: commit: ... HEAD@2: checkout: 从...移动到 ... HEAD@ 3:签出:从...移动到... HEAD@4:克隆:从#sorry 对于格式 SO 显然不允许 cmets 中的多行 这也包括原始提交,最好的解决方案是使用@PlagueHammer (***.com/a/2016954/624048) 提供的命令【参考方案8】:

方便的 git 别名,用于在 current 分支中查找未推送的提交:

alias unpushed = !GIT_CURRENT_BRANCH=$(git name-rev --name-only HEAD) && git log origin/$GIT_CURRENT_BRANCH..$GIT_CURRENT_BRANCH --oneline

这基本上是做什么的:

git log origin/branch..branch

但也确定当前分支名称。

【讨论】:

这太棒了!对于那些不熟悉别名的人,只需将它们添加到您的 ~/.gitconfig 文件中的 [alias] 部分。 在 bash 中复制/粘贴不起作用,但脚本非常有用且易于理解 这不是 bash 别名,正如@GaryHaran 指出的那样。还有一个用于添加别名的 git 命令:git alias <alias-name> <command> 在这种情况下,该命令应该用单引号引起来,以便从 shell 中转义特殊字符。 那就是:git config --global alias.unpushed '!GIT_CURRENT_BRANCH=$(git name-rev --name-only HEAD) && git log origin/$GIT_CURRENT_BRANCH..$GIT_CURRENT_BRANCH --oneline' 这似乎与 git log @u.. 基本相同 - 请参阅 another answer.【参考方案9】:

你可以试试……

gitk

我知道这不是一个纯粹的命令行选项,但如果您已安装它并且在 GUI 系统上,这是一个很好的方式来准确查看您正在寻找的内容以及更多内容。

(我真的有点惊讶到目前为止没有人提到它。)

【讨论】:

gitk --all 查看所有分支。 tig 是 ncurses 的替代品。 @justin-ohms gitk 太棒了!从来不知道这存在!方便在漂亮的 UI 中浏览更改。 @ray tig 在“仅限终端”的情况下最有用——在这种情况下您无法访问桌面 GUI。第一次了解它!有趣:tiggit 的倒数!【参考方案10】:

git branch -v 将为每个本地分支显示它是否“领先”。

【讨论】:

是的,如果分支devel 上存在未推送的提交,则对应的行将是* devel 8a12fc0 [ahead 1] commit msg* 将仅在与签出分支对应的行上)。 ahead 1 表示“提前一个提交”,即有一个未推送的提交。 不是git branch -vv吗?参照。 docs:“如果给出两次,也打印上游分支的名称(另见 git remote show )。” 这不是打印上游分支的名称,而是为每个本地分支打印behind和/或ahead,这足以解决OP的问题(检测未推送的提交) . git branch -v 就足够了,刚刚用 Git 2.16.2 再次测试 :) -vv 很有用,因为它显示了与远程同步的分支和根本未推送的分支之间的差异。 (只有一个 -v,它们在显示中的显示相同。)【参考方案11】:

我使用以下别名仅获取已提交但尚未推送的文件列表(和状态)(对于当前分支)

git config --global alias.unpushed \
"diff origin/$(git name-rev --name-only HEAD)..HEAD --name-status"

那就做吧:

git unpushed

【讨论】:

看起来很有趣,但在我的情况下 $(git name-rev --name-only HEAD) 是“未定义” 我不得不将diff改为git diff,因为它默认使用diff (GNU diffutils) 3.7【参考方案12】:

我相信最典型的做法是运行类似:

git cherry --abbrev=7 -v @upstream

不过,我个人更喜欢跑步:

git log --graph --decorate --pretty=oneline --abbrev-commit --all @upstream^..

显示来自 all 未在上游合并的分支的提交,加上上游中的最后一次提交(显示为所有其他提交的根节点) .我经常使用它,所以我为它创建了别名noup

git config --global alias.noup \
'log --graph --decorate --pretty=oneline --abbrev-commit --all @upstream^..'

【讨论】:

【参考方案13】:
git cherry -v

这将列出您的本地评论历史记录(尚未推送)以及相应的消息

【讨论】:

Duplicate answer on same question.【参考方案14】:

我建议你去看看脚本https://github.com/badele/gitcheck,我已经编写了这个脚本来检查你所有的 git 存储库,它会显示谁没有提交,谁没有推/拉。

这里是一个示例结果

【讨论】:

你能解释一下如何让这个插件在 Windows 机器上工作吗?我正在尝试运行 pip,但命令行中缺少该命令。我安装了 Python,但我不确定它是否足够。 @KonradSzałwiński 我没有 Windows 机器,但在这个主题(***.com/questions/4750806/…)中,用户似乎回答了你的问题 :)。但我没有在 Windows 中测试过,我不确定它是否有效。 @KonradSzałwiński ChristianTremblay github 贡献者添加了 Windows 支持。现在 gitcheck 在 Windows 上工作。你可以在github.com/badele/gitcheck下载它 现在,您还可以直接从 docker 容器中使用 gitcheck(文件在您的主机中)有关更多信息,请参阅 gitcheck github 项目 感谢您发布此信息,它似乎真的很有用。我尝试安装,但安装后我找不到运行它的脚本的位置。 $ pip install git+git://github.com/badele/gitcheck.git 收集 git+git://github.com/badele/gitcheck.git 克隆 git://github.com/badele/gitcheck.git 到 c :\users\u6041501\appdata\local\temp\pip-bxt472z_-build 安装收集的包:gitcheck 运行 setup.py install for gitcheck:开始 运行 setup.py install for gitcheck:完成状态 'done' 成功安装 gitcheck-0.3 .22【参考方案15】:

这不是错误。您可能看到的是自动合并失败后的 git 状态,其中从远程获取更改但尚未合并。

要查看本地 repo 和远程之间的提交,请执行以下操作:

git fetch

这是 100% 安全的,不会模拟您的工作副本。如果有更改git status 将显示X commits ahead of origin/master

您现在可以显示在远程但不在本地的提交日志:

git log HEAD..origin

【讨论】:

【参考方案16】:

这对我来说效果更好:

git log --oneline @upstream..

或:

git log --oneline origin/(remotebranch)..

【讨论】:

对于其他想知道的人,@upstream 是字面意思(upstream 是一个神奇的词),而 remotebranch 只是您的分支的名称。【参考方案17】:

有一个名为unpushed 的工具可以扫描指定工作目录中的所有 Git、Mercurial 和 Subversion 存储库,并显示未提交文件和未推送提交的列表。 Linux下安装很简单:

$ easy_install --user unpushed

$ sudo easy_install unpushed

在系统范围内安装。

用法也很简单:

$ unpushed ~/workspace
* /home/nailgun/workspace/unpushed uncommitted (Git)
* /home/nailgun/workspace/unpushed:master unpushed (Git)
* /home/nailgun/workspace/python:new-syntax unpushed (Git)

请参阅unpushed --help 或official description 了解更多信息。它还有一个 cronjob 脚本unpushed-notify,用于在屏幕上通知未提交和未推送的更改。

【讨论】:

【参考方案18】:

要轻松列出所有未推送的提交所有分支,您可以使用以下命令:

 git log --branches  @u..

【讨论】:

【参考方案19】:

如果未推送的提交数是个位数,通常是这样,最简单的方法是:

$ git checkout

git 通过告诉您相对于您的来源您“提前 N 次提交”来响应。所以现在在查看日志时记住这个数字。如果您“领先 3 次提交”,则历史上的前 3 次提交仍然是私有的。

【讨论】:

【参考方案20】:

类似:查看未合并的分支:

git branch --all --no-merged

这些可能是可疑的,但我推荐 cxreg 的答案

【讨论】:

【参考方案21】:

一种处理方式是列出在一个分支上可用但在另一个分支上不可用的提交。

git log ^origin/master master

【讨论】:

'^' 字符有什么作用? @AranMulholland 它代表不在这里。【参考方案22】:

我真的迟到了,我不确定它何时实施,但要看看git push 会做什么,只需使用--dry-run option

$ git push --dry-run
To ssh://bitbucket.local.lan:7999/qarepo/controller.git
   540152d1..21bd921c  imaging -> imaging

【讨论】:

【参考方案23】:

如上所述:

git diff origin/master..HEAD

但是如果你使用的是 git gui

打开gui界面后,选择“Repository”->在“Visualize History”下

注意:有些人喜欢使用 CMD Prompt/Terminal,而有些人喜欢使用 Git GUI(为简单起见)

【讨论】:

git gui 中的可视化选项就是其中一个。【参考方案24】:

如果你有 git 子模块...

无论您使用git cherry -v 还是git logs @u.. -p,都不要忘记通过以下方式包含您的子模块 git submodule foreach --recursive 'git logs @u..'.

我正在使用以下 bash 脚本来检查所有这些:

    unpushedCommitsCmd="git log @u.."; # Source: https://***.com/a/8182309

    # check if there are unpushed changes
    if [ -n "$($getGitUnpushedCommits)" ]; then # Check Source: https://***.com/a/12137501
        echo "You have unpushed changes.  Push them first!"
        $getGitUnpushedCommits;
        exit 2
    fi

    unpushedInSubmodules="git submodule foreach --recursive --quiet $unpushedCommitsCmd"; # Source: https://***.com/a/24548122
    # check if there are unpushed changes in submodules
    if [ -n "$($unpushedInSubmodules)" ]; then
        echo "You have unpushed changes in submodules.  Push them first!"
        git submodule foreach --recursive $unpushedCommitsCmd # not "--quiet" this time, to display details
        exit 2
    fi

【讨论】:

【参考方案25】:

这是我的便携式解决方案(无需额外安装也可以在 Windows 上运行的 shell 脚本),它显示了所有分支与原点的差异:git-fetch-log

示例输出:

==== branch [behind 1]

> commit 652b883 (origin/branch)
| Author: BimbaLaszlo <bimbalaszlo@gmail.com>
| Date:   2016-03-10 09:11:11 +0100
|
|     Commit on remote
|
o commit 2304667 (branch)
  Author: BimbaLaszlo <bimbalaszlo@gmail.com>
  Date:   2015-08-28 13:21:13 +0200

      Commit on local

==== master [ahead 1]

< commit 280ccf8 (master)
| Author: BimbaLaszlo <bimbalaszlo@gmail.com>
| Date:   2016-03-25 21:42:55 +0100
|
|     Commit on local
|
o commit 2369465 (origin/master, origin/HEAD)
  Author: BimbaLaszlo <bimbalaszlo@gmail.com>
  Date:   2016-03-10 09:02:52 +0100

      Commit on remote

==== test [ahead 1, behind 1]

< commit 83a3161 (test)
| Author: BimbaLaszlo <bimbalaszlo@gmail.com>
| Date:   2016-03-25 22:50:00 +0100
|
|     Diverged from remote
|
| > commit 4aafec7 (origin/test)
|/  Author: BimbaLaszlo <bimbalaszlo@gmail.com>
|   Date:   2016-03-14 10:34:28 +0100
|
|       Pushed remote
|
o commit 0fccef3
  Author: BimbaLaszlo <bimbalaszlo@gmail.com>
  Date:   2015-09-03 10:33:39 +0200

      Last common commit

为日志传递的参数,例如可以使用--oneline--patch

【讨论】:

【参考方案26】:
git show

将显示本地提交中的所有差异。

git show --name-only

将显示本地提交 ID 和提交名称。

【讨论】:

git show 只显示最近的提交,无论它是否被推送到远程,它都不会显示所有未推送的提交。【参考方案27】:
git diff origin

假设您的分支设置为跟踪原点,那么这应该会向您显示差异。

git log origin

将为您提供提交的摘要。

【讨论】:

git log origin 将显示已被推送的提交,但不会显示haven'的提交t 被推送,这更符合原始海报的要求。

以上是关于查看未推送的 Git 提交的主要内容,如果未能解决你的问题,请参考以下文章

Git常用命令记录

Git 状态 和 查看历史提交

[git] github 推送以及冲突的解决

Git常用命令

Git更改未推送提交的作者[重复]

如何在 git 中编辑任何提交的提交消息? [复制]