简体   繁体   English

忘记搬到另一个分支,而不是掌握Git的人

[英]forget to move to another branch than master with Git

I'm using Git with a rails project. 我在Rails项目中使用Git

Today i make a lot of changes and i forget to move to another branch , so all these changes are in the master branch but not committed yet . 今天,我做了很多更改,但忘记了移到 another branch ,因此所有这些更改都在master分支中,但尚未提交

this is what i get when i do git status command : 这是我执行git status命令时得到的:

# On branch master
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   app/controllers/sessions_controller.rb
#   modified:   app/controllers/users_controller.rb
#   modified:   app/helpers/sessions_helper.rb
#   modified:   app/models/user.rb
# .....

#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   app/assets/javascripts/password_resets.js.coffee
#   app/assets/stylesheets/password_resets.css.scss
#   app/controllers/password_resets_controller.rb
# .....
# ......
no changes added to commit (use "git add" and/or "git commit -a")

how i can solve this error and move all these untracked files from master to another branch already exists ? 我如何解决此错误并将所有这些未跟踪的文件从master 移到另一个分支已经存在 thank you. 谢谢。

Just create a new branch and then commit, eg: 只需创建一个新分支,然后提交即可,例如:

git checkout -b my_branch
git commit -am "My commit."

You simply need to create new branch. 您只需要创建新分支。

Once you create a branch all the changes will be in the new branch. 创建分支后,所有更改都将在新分支中。

and then clean your old stuff from master 然后从师傅那里清理你的旧东西

// Checkout new branch
git checkout -b my_branch

// Prepare files for commit
git add .

// Commit changes
git commit -m "Your commit message"

// delete the dirty master
git branch -D master

// Now we are going to clean your changes from the master branch
// the -f is important in case you skipped the previous command to delete your master
git checkout -f master 

If there are no commits marked C1, C2, etc. below 如果下面没有标记为C1,C2等的提交

You're in the simple case; 您处于简单情况下; just use Henrik N's answer . 只需使用Henrik N的答案即可

If there is a tracking branch 如果有跟踪分支

Your updated question/comments suggests that you have both committed changes and uncommitted changes, and you did them all on some tracking branch, such as master that tracks origin/master or devel that tracks origin/devel , but that you have not pushed any of them yet. 您更新的问题/注释表明您已经提交了更改和未提交的更改,并且都在某个跟踪分支上完成了所有操作,例如master跟踪origin/masterdevel跟踪origin/devel ,但是您没有推送任何他们呢。 (I'll assume master but you can just change each master to the feature/development/whatever branch name below.) (我假设是master但是您可以将每个master更改为下面的功能/开发/任何分支名称。)

As a diagram, your repo's commit tree and working directory/index now looks something like this: 如图所示,您的存储库的提交树和工作目录/索引现在看起来像这样:

M1 -...- M5 -- M6                    <-- origin/master
                 \
                  C1 -- C2           <-- master, HEAD=master
                          \
                           i, w      <-- "index" and working-tree files

Here i is the stuff in the index ( git add dir/file1 , git rm file2 , etc), which git status shows as changes to be committed , and w is the stuff in your working directory that git status shows as changes not staged for commit . 在这里, i是索引中的内容( git add dir/file1git rm file2等), git status显示为changes to be committedw是工作目录中的内容, git status显示为changes not staged for commit

Here's what you want it to look like: 这是您想要的样子:

M1 -...- M5 -- M6                    <-- master, origin/master
                 \
                  C1 -- C2           <-- my_branch, HEAD=my_branch
                          \
                           i, w      <-- "index" and working-tree files

Remember that branch labels are like sticky-notes ("yellow stickies" or "Post-It® notes" or whatever): they have a name written on them and are pasted on to a commit. 请记住,分支标签就像便笺(“黄色便笺”或“Post-It®便笺”之类):它们上面写有名称,并粘贴到提交上。 So what you have to do is add a new sticky-note, my_branch , pointing to commit C2, and also make HEAD refer to the new branch name: 因此,您要做的是添加一个新的粘滞便笺my_branch ,指向提交C2,并使HEAD引用新的分支名称:

git checkout -b my_branch

This uses the previous value of HEAD to name the commit that my_branch is pasted-on-to. 这使用HEAD的先前值来命名my_branch粘贴到的提交。 Since that commit is C2 you now have both master and my_branch here. 由于该提交是C2您现在在这里既有master也有my_branch It then rewrites HEAD to point to the name my_branch . 然后,它重写HEAD以指向名称my_branch Now you have: 现在您有了:

M1 -...- M5 -- M6                    <-- origin/master
                 \
                  C1 -- C2           <-- master, my_branch, HEAD=my_branch
                          \
                           i, w      <-- "index" and working-tree files

Now you need to move the sticky-note labeled master to point back where origin/master points. 现在,您需要将标记为“ master的粘滞便笺移回origin/master指向的位置。 There are two ways to do this, with git reset , or with git branch . 有两种方法可以执行此操作: git resetgit branch Using git reset is harder, so let's do it with git branch : 使用git reset比较困难,所以让我们用git branch完成它:

git branch -f master origin/master

The -f (force) flag tells git branch to change an existing sticky-note, rather than failing because it exists, and origin/master gives which commit master should point-to: so git peels the label off C2 and pastes it on M6 , and you have the setup you wanted (the 2nd diagram). -f (强制)标志告诉git branch更改现有的便笺,而不是因为它存在而失败,并且origin/master给出master应该指向的提交便笺:因此git将标签从C2剥离并将其粘贴到M6 ,然后您便有了所需的设置(第二张图)。


Summary: it's just two commands: 简介:这只是两个命令:

git checkout -b my_branch           # create new branch and change HEAD
git branch -f master origin/master  # restore master to origin/master

You're now ready to check in changes as usual, on branch my_branch . 现在您可以像往常一样在分支my_branch上签入更改。 ( git add , git rm , git commit as needed.) That will add a new commit C3: (根据需要git addgit rmgit commit 。)这将添加一个新的提交C3:

M1 -...- M5 -- M6                    <-- master, origin/master
                 \
                  C1 -- C2 -- C3     <-- my_branch, HEAD=my_branch

What if there is no tracking branch? 如果没有跟踪分支怎么办?

Well, that's OK, it's just a little harder. 好吧,没关系,只是有点难。 Go back to the "have now" and "want" diagrams. 返回到“现在拥有”和“想要”图。 In these diagrams, the commit I labeled M6 is the one you want master to name. 在这些图中,我标记为M6的提交是您希望master命名的提交。 You now have to find M6. 现在,您必须找到 M6。 Commits have these long hexadecimal-numeric (SHA-1) "true names" that never change, like 5e013711f5d6eb3f643ef562d49a131852aa4aa1 for example. 提交具有永不更改的长十六进制数字(SHA-1)“真实名称”,例如5e013711f5d6eb3f643ef562d49a131852aa4aa1。 ( git rev-parse HEAD will show the "true name" for the current, ie, HEAD , commit.) You can find that "true name", or you can find some alternate or abbreviated name that also names the same thing. git rev-parse HEAD将显示当前的“真实名称”,即HEAD ,commit。)您可以找到该“真实名称”,也可以找到一些替换名称或缩写名称,它们也可以命名相同的名称。

There are a whole lot of options for names, but let's stick with numbers that come out of git log and git log --oneline . 名称有很多选择,但让我们继续使用git loggit log --oneline The latter gives you something like this: 后者给你这样的东西:

97206f5 peerish: set socket options earlier
4881af5 add semtest.c
b3f8bea fdm: repair example

where the number is an abbreviated SHA-1 and the text is the first line of the commit message. 其中数字是SHA-1的缩写,文本是提交消息的第一行。 Since the logs are shown in reverse order, the top line is the most recent commit ( C2 in the example above), and then each next line is the next one back (well, it's more complicated with merges, but close enough). 由于日志以相反的顺序显示,因此第一行是最新的提交(上例中为C2 ),然后每一行是下一个提交(嗯,合并比较复杂,但足够接近)。

Let's say that from the above, you can immediately tell that the commit I labeled M6 is b3f8bea , ie, that you need to skip two commits. 假设从上面可以立即看出,我标记为M6的提交是b3f8bea ,即您需要跳过两次提交。 Simply supply that value as the last argument to git branch : 只需将该值作为git branch的最后一个参数即可:

git branch -f master b3f8bea

If your repo is huge and old, or has a lot of merge commits, you might want your logs to include more "decoration". 如果您的存储库很大且很旧,或者有很多合并提交,那么您可能希望您的日志包含更多的“装饰”。 I got these aliases from somewhere long ago: 我早在某个地方就得到了这些别名:

[alias]
    lol = git log --graph --decorate --oneline
    lola = git log --graph --decorate --oneline --all

so that I can run git lol and git lola . 这样我就可以运行git lolgit lola

Alternatively, if you know for sure there were exactly two commits, master~2 (and in this case, after adding my_branch , my_branch~2 ) will get you the same SHA-1. 另外,如果你知道肯定有确切两次提交, master~2 (在这种情况下,添加后my_branchmy_branch~2 )将让你同样的SHA-1。 The git rev-parse command shows you exactly which SHA-1 any given name "means". git rev-parse命令可以准确显示给定名称“ means”是哪个SHA-1。 In one repo I have here, HEAD~2 is the same as origin/featureX : 在一个回购我这里有, HEAD~2相同origin/featureX

$ git rev-parse HEAD~2
0f5a13497dd3da8aff8e452c8f56630f83253e79
$ git rev-parse origin/featureX
0f5a13497dd3da8aff8e452c8f56630f83253e79

but in general git log (or git lol , etc.) will get you the raw SHA-1 and you can add labels from there, as needed. 但通常git log (或git lol等)将为您提供原始SHA-1,并且您可以根据需要从那里添加标签。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM