Git基本工作流程

27

可能的重复问题:
git push错误“[remote rejected] master -> master (branch is currently checked out)”

我是Git的新手,正在尝试将其用于本地grails项目。
我遵循的步骤:

  1. 创建grails项目
  2. 进入项目目录并执行git init
  3. 将项目中的所有文件添加到暂存区并提交
  4. 仓库中的git状态会显示以下消息:

    BXX@BXX-PC /c/Work/Grails/projects/yyy/tables (master)
    $ git status
    # On branch master
    nothing to commit (working directory clean)
    
  5. 尝试将其保持为主分支,通过克隆仓库进行更改,稍后将更改推回。为此:

  6. 在我的IDE中,检出项目(IntelliJ)。实际上,这将把项目克隆到另一个目录中。

  7. 进行更改并提交项目。

  8. 将本地更改推送到主分支。

  9. 15:41:56.249: git push -v origin master
    Pushing to c:/Work/Grails/projects/xxx/tables
    remote: error: refusing to update checked out branch: refs/heads/master        
    remote: error: By default, updating the current branch in a non-bare repository        
    remote: error: is denied, because it will make the index and work tree inconsistent        
    remote: error: with what you pushed, and will require 'git reset --hard' to match        
    remote: error: the work tree to HEAD. 
    

克隆的仓库状态为:

$ git status
# On branch master
# Your branch is ahead of 'origin/master' by 1 commit.
#
nothing to commit (working directory clean)
请帮助我理解这个问题。有没有更好的工作流程可以遵循?我可能能够通过Intellij初始化存储库,然后尝试在主分支上工作。仍然不确定上面的问题是什么。
谢谢。

只需将代码推送到不同的分支并进行合并:git push origin master:foo - kenorb
4个回答

45
问题在于您试图向非裸库推送。非裸库是具有关联工作树的库(即,文件实际上已检出到磁盘)。默认情况下,Git 不允许您向非裸库推送;向非裸库推送只更新 Git 的内部数据结构,并且不会更改工作树(磁盘上的文件),这意味着如果您随后返回推送到的库并开始使用文件,则将使用旧版本的文件。当您尝试提交更改时,自然会导致问题。
最好的方法是将其推送到存储库,这是通过在创建存储库时传递--bare标志创建的存储库:
$ mkdir new_repo
$ cd new_repo
$ git --bare init

当然,裸仓库没有任何文件被检出,因此你不能直接在其中工作(你必须先克隆它)。

如果你只是在本地开发时使用Git仓库(不共享或提供Git仓库),则无需拥有远程仓库来推送;你可以在单个本地非裸仓库的副本上工作。


非常感谢您详细的回复。事实上,我阅读了您在 SO 上类似问题的一些答案。我可能会遵循您的建议,使用一个本地仓库,然后每当需要时克隆。但是,是否有可能我先检入(commit)主仓库,然后再尝试将克隆的仓库推送到主仓库?我很好奇有人如何克隆我的仓库并在后期将其推送到主分支。我非常感谢您的评论,这样我就不会在长期内后悔。。再次感谢。 - bsr
注意:有一种情况下,将代码推送到非裸仓库是可以的:https://dev59.com/1lDTa4cB1Zd3GeqPKZim#10731806。 - VonC

34

首先,您不需要克隆本地存储库。您可以使用分支将开发分成同一个存储库中的不同部分。

Git是一种分布式版本控制系统,如果您之前有使用Subversion或CVS的经验,需要改变思维方式。

Git非常灵活,您可以使用不同的工作流程。克隆存储库更适用于团队合作,而不是用于本地开发(个人意见)。

分支是一个很好的替代方案。

让我们将您的存储库的主要分支设置为生产就绪代码。让我们为开发创建另一个分支:

$ git checkout -b development master

现在你正在开发分支development

你可以为每个想要开发的功能使用不同的分支,这很容易且有帮助。

假设你想要实现一些新功能,你需要创建一个新的分支:

$ git checkout -b newfeature development

现在你可以处理你的代码,添加文件,提交等等。

接下来,您需要将新开发的功能合并开发分支中:

$ git add .
$ git commit -m "My last changes for the new feature"
$ git checkout development
$ git merge newfeature

现在你的来自 newfeature 分支的新代码已合并到 development 分支中。

将来某个时候,当你确定在 development 分支上的代码达到了一定的里程碑,你可以将 development 分支上的所有更改合并到 master 分支中。

这是一个非常基本的工作流程,对于许多分支来说都很有帮助。

我的建议是:多了解git、分支和暂存(用于快速修复非常非常非常有用)。随着时间的推移,你会从使用git中受益匪浅。

祝你好运。


非常感谢您提供的逐步解答。您说得完全正确,我仍然在想传统的SCM模型。我之前只使用过ClearCase和Microsoft SourceSafe...所以,您可以想象 :-) ... 您的回答帮助我整合了许多关于Git的概念..非常感谢您... - bsr

10

这是一个成功的Git工作流程的最清晰、最全面的描述。它基本涵盖了Sergey所建议的内容,并增加了一些非常有帮助的图形。

一个成功的Git分支模型

作者还建议在合并时包括--no-ff标记,以记录历史上存在功能分支的事实。


3
当我尝试解决同样的问题时,我最终来到了这里,幸运的是有更好的答案:Git push error '[remote rejected] master -> master (branch is currently checked out)'。你应该查看一下它。特别是因为很容易陷入这种情况。对我来说,我只是创建了一个目录并使用git init将其初始化为我的新“共享存储库”。由于我们的网络完全被锁定,我们无法共享目录或访问GitHub,所以它在USB键上。然后我将所有源代码复制到该目录中,添加了它,提交了它,然后克隆了生成的存储库到我的本地驱动器,使其成为我的起点。我认为我以后可以使GitHub远程并且不再使用共享的USB存储库。但是,我在本地驱动器上进行的第一个更改并尝试推送到远程(关键存储库)时,给了我这个消息,因为关键存储库不是“裸”的。所有原始文件仍然存在。请参考链接问题中评分最高的答案,以了解该怎么做。要点是在共享存储库中设置一个标志,使其认为它是裸的,然后删除除.git子目录之外的所有内容,然后您的推送就会起作用。

谢谢您回答了我提出的问题。其他答案都充满了有用的Git知识,但只有您的回答帮助我解决了当前的问题。 - Mark Roberts

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接