* [BUG] git checkout <branch> allowed with uncommitted changes @ 2011-10-13 8:40 arQon 2011-10-13 10:48 ` Nguyen Thai Ngoc Duy 2011-10-13 15:09 ` Michael J Gruber 0 siblings, 2 replies; 36+ messages in thread From: arQon @ 2011-10-13 8:40 UTC (permalink / raw) To: git Which, as you'd expect, results in both the on-disk copies and other branches becoming corrupted. Tested on git versions 1.7.6 and 1.7.7 (msysgit) http://benno.id.au/blog/2011/10/01/git-recursive-merge-broken describes something that sounds similar, but that's supposedly fixed on 1.7.7, whereas this happens on that as well. master is a tracking branch, "ttfcon" is the branch I was using to develop a change. Got to a good point on the branch, merged it in: $ git co master $ git merge ttfcon Updating b9f0c75..6280b7a Fast-forward .gitignore | 2 ++ code/renderer/tr_font.cpp | 27 ++++++++------------------- 2 files changed, 10 insertions(+), 19 deletions(-) $ git st # On branch master # Your branch is ahead of 'origin/master' by 3 commits. back to the branch to mess around with a couple of things to be sure this is what i want to push $ git co ttfcon do stuff $ git st # On branch ttfcon # 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: code/freetype-2.3.11/builds/win32/visualc/freetype.vcproj # modified: code/renderer/tr_font.cpp so far so good... $ git ci -m "blah" code/freetype-2.3.11/builds/win32/visualc/freetype.vcproj 1 files changed, 4 insertions(+), 0 deletions(-) note that tr_font is locally modified and still *not committed* at this point. $ git co master M code/renderer/tr_font.cpp Switched to branch 'master' Your branch is ahead of 'origin/master' by 3 commits. boom. instead of rejecting the branch change, git switches branches anyway, and doesn't do anything about the uncommitted changes in the file itself - meaning they're now effectively "in" master because they're still on disk, so now the master is poisoned. "git st" does show the change: # On branch master # Changes not staged for commit: # modified: code/renderer/tr_font.cpp but it's a change I never MADE on this branch (ie master), only on the other branch. "git diff" is just as confused as I am: $ git diff ttfcon --- a/code/renderer/tr_font.cpp +++ b/code/renderer/tr_font.cpp + // git branch bug So it's picking up the difference between the two branches, but as far as the *actual file* goes, master now has a line in it that shouldn't be there. I'm just trying out git as a possible replacement for SVN, so maybe I'm mistaken about what "should" happen, but AIUI git switching branches with uncommitted changes is a bug (and given that it poisoned a branch that I wasn't on, it certainly looks like one). A couple of days ago it DID complain when I tried to switch with uncommitted files still present, so it was working properly then. I have no idea what's made it happy to ignore them now: nothing's changed that I know of. At this point, reverting the master with "checkout --" also wipes out the changes on the other branch. It's like the merge symlinked the two branches rather than, well, merging them. If this is user error, and merge is supposed to break the tree like that, then sorry for wasting your time, but I can't find anything in the docs that says (or even suggests) that it should, so... Thanks. ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [BUG] git checkout <branch> allowed with uncommitted changes 2011-10-13 8:40 [BUG] git checkout <branch> allowed with uncommitted changes arQon @ 2011-10-13 10:48 ` Nguyen Thai Ngoc Duy 2011-10-13 10:59 ` Alexey Shumkin 2011-10-13 15:09 ` Michael J Gruber 1 sibling, 1 reply; 36+ messages in thread From: Nguyen Thai Ngoc Duy @ 2011-10-13 10:48 UTC (permalink / raw) To: arQon; +Cc: git On Thu, Oct 13, 2011 at 7:40 PM, arQon <arqon@gmx.com> wrote: > $ git co master > M code/renderer/tr_font.cpp > Switched to branch 'master' > Your branch is ahead of 'origin/master' by 3 commits. ... > At this point, reverting the master with "checkout --" also wipes out the > changes on the other branch. It's like the merge symlinked the two branches > rather than, well, merging them. It does show you that there are changes in the working tree and you could have switched back with "git co -", done whatever you want with your changes then switched to master again. > A couple of days ago it DID complain > when I tried to switch with uncommitted files still present, so it was working > properly then. I have no idea what's made it happy to ignore them now: > nothing's changed that I know of. git tries to keep all changes on working tree you have. If you have changes in file A and the new branch changes in file B, fine. If the new branch also changes in file A too, it'll complain because otherwise it may overwrite your changes. What it actual does is "Two way merge", there is a table in "git read-tree" man page that describes exactly how it is done, what cases would fail... I see it as more choices. As I said above, it does tell you there are changes and you could do something. You could make alias "co" that check for worktree/index cleanliness before calling checkout. Something like this maybe (I have not tested it) git config alias.co '!git update-index --refresh && git diff-files --quiet && git diff-index --cached --quiet HEAD && git checkout "$@"' A config key to enforce this may be nice. I don't know, I have never had problems with current behavior. -- Duy ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [BUG] git checkout <branch> allowed with uncommitted changes 2011-10-13 10:48 ` Nguyen Thai Ngoc Duy @ 2011-10-13 10:59 ` Alexey Shumkin 2011-10-13 11:51 ` arQon 0 siblings, 1 reply; 36+ messages in thread From: Alexey Shumkin @ 2011-10-13 10:59 UTC (permalink / raw) To: Nguyen Thai Ngoc Duy; +Cc: arQon, git > On Thu, Oct 13, 2011 at 7:40 PM, arQon <arqon@gmx.com> wrote: > > $ git co master > > M code/renderer/tr_font.cpp > > Switched to branch 'master' > > Your branch is ahead of 'origin/master' by 3 commits. > > ... > > > At this point, reverting the master with "checkout --" also wipes > > out the changes on the other branch. It's like the merge symlinked > > the two branches rather than, well, merging them. > > It does show you that there are changes in the working tree and you > could have switched back with "git co -", done whatever you want with > your changes then switched to master again. > > > A couple of days ago it DID complain > > when I tried to switch with uncommitted files still present, so it > > was working properly then. I have no idea what's made it happy to > > ignore them now: nothing's changed that I know of. > > git tries to keep all changes on working tree you have. If you have > changes in file A and the new branch changes in file B, fine. If the > new branch also changes in file A too, it'll complain because > otherwise it may overwrite your changes. What it actual does is "Two > way merge", there is a table in "git read-tree" man page that > describes exactly how it is done, what cases would fail... > > I see it as more choices. As I said above, it does tell you there are > changes and you could do something. You could make alias "co" that > check for worktree/index cleanliness before calling checkout. > Something like this maybe (I have not tested it) > > git config alias.co '!git update-index --refresh && git diff-files > --quiet && git diff-index --cached --quiet HEAD && git checkout "$@"' > > A config key to enforce this may be nice. I don't know, I have never > had problems with current behavior. I agree with the explanation and I like current behavior, as well. 2arQon: Your expectations is based on SVN experience but as ex-SVN-user, too, I can (and I want to) say: Git is more flexible and powerful tool then SVN is. Take is power and change your expectations, and your life will become better ))) ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [BUG] git checkout <branch> allowed with uncommitted changes 2011-10-13 10:59 ` Alexey Shumkin @ 2011-10-13 11:51 ` arQon 2011-10-13 12:22 ` Andreas Ericsson 2011-10-13 12:42 ` arQon 0 siblings, 2 replies; 36+ messages in thread From: arQon @ 2011-10-13 11:51 UTC (permalink / raw) To: git Snipping the bug and focusing on one of the after-effects of the bug is, unfortunately, not helpful to me unless I'm missing your point (which is certainly possible). git switched branches while there were uncommitted files. It's not supposed to do this, ever, unless given -f or -m, and it broke the tree as a result. Even *with* -f or -m, the behavior I described is incorrect. The git docs seem to agree with me, which is why there's git stash. If the docs are wrong, fine, though it seems pretty strange to have a change on BranchA appear by magic "in" BranchB without any merging. What I'm after is an understanding / explanation of how something that isn't supposed to happen, does. I don't care if it's "Because I'm an idiot", "Because git is broken", or even "Make sure your config has 'git.makebranchesworkproperly = true' in it, the default is false". If there is no explanation for why git switches branches when there are still uncommitted files, and there doesn't seem to be, then it's a pretty catastrophic bug and fixing it would be a Good Thing. *AFAICT*, committing *a* file is what triggers it. If you commit -a, which is what all the commits prior to this were, it works properly. You change branches, and the files on the disk become what they should be. If you commit nothing, you correctly get the "uncommitted files" error. If you do a partial commit though, your tree breaks. Like I say, if the man page, quote: "If you have local modifications to one or more files that are different between the current branch and the branch to which you are switching, the command refuses to switch branches in order to preserve your modifications in context." is wrong, and this behavior is deliberate, that's fine. Bizarre, but fine in the sense that git is doing what it's supposed to (regardless of how counterintuitive and destructive it is). If the man page is right though, this is a bug. Maybe it's only in msysgit, but this is the second time it's happened, so hopefully it's fairly easy to reproduce. ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [BUG] git checkout <branch> allowed with uncommitted changes 2011-10-13 11:51 ` arQon @ 2011-10-13 12:22 ` Andreas Ericsson 2011-10-13 13:09 ` arQon 2011-10-13 13:58 ` [BUG] " arQon 2011-10-13 12:42 ` arQon 1 sibling, 2 replies; 36+ messages in thread From: Andreas Ericsson @ 2011-10-13 12:22 UTC (permalink / raw) To: arQon; +Cc: git On 10/13/2011 01:51 PM, arQon wrote: > Snipping the bug and focusing on one of the after-effects of the bug is, > unfortunately, not helpful to me unless I'm missing your point (which is > certainly possible). > > git switched branches while there were uncommitted files. It's not supposed to > do this, ever, unless given -f or -m, and it broke the tree as a result. Even > *with* -f or -m, the behavior I described is incorrect. > The git docs seem to agree with me, which is why there's git stash. If the docs > are wrong, fine, though it seems pretty strange to have a change on BranchA > appear by magic "in" BranchB without any merging. > > What I'm after is an understanding / explanation of how something that isn't > supposed to happen, does. I don't care if it's "Because I'm an idiot", "Because > git is broken", or even "Make sure your config has 'git.makebranchesworkproperly > = true' in it, the default is false". If there is no explanation for why git > switches branches when there are still uncommitted files, and there doesn't seem > to be, then it's a pretty catastrophic bug and fixing it would be a Good Thing. > > *AFAICT*, committing *a* file is what triggers it. > If you commit -a, which is what all the commits prior to this were, it works > properly. You change branches, and the files on the disk become what they should > be. > If you commit nothing, you correctly get the "uncommitted files" error. > If you do a partial commit though, your tree breaks. > > Like I say, if the man page, quote: > "If you have local modifications to one or more files that are different between > the current branch and the branch to which you are switching, the command > refuses to switch branches in order to preserve your modifications in context." This means that if fileX on branchA is different from fileX on branchB and you *also* have local modifications to fileX, git will refuse to switch branches. If, on the other hand branchA:fileX == branchB:fileX and you have modifications to fileX in your work tree, there's no reason to refuse the branch change. Partly because nothing will be lost and partly because you can just switch branches back if you decide you've switched branches before committing things to the first branch. > is wrong, and this behavior is deliberate, that's fine. Bizarre, but fine in > the sense that git is doing what it's supposed to (regardless of how > counterintuitive and destructive it is). > If the man page is right though, this is a bug. Maybe it's only in msysgit, > but this is the second time it's happened, so hopefully it's fairly easy to > reproduce. > It's not a bug. You just read the manpage a bit wrong. Consider this scenario: $dev works on featureA on branchA, modifying fileX, fileZ and fileY and then does a commit of fileZ and fileY, but realizes that the changes in fileX will be good for developing featureB as well, so he changes to a separate branch to do the update to fileX and be able to merge those changes to both branchA and branchB. I've done this myself on numerous occasions when re-working small project- local API's, and it's very, very handy indeed. If git would refuse me to change branches without first committing everything I'd have to first commit the change separately, switch branch, cherrypick the change, go back to the first branch and remove the commit I made there, merge the other branch where the commit really belonged and only then I could go on about my business. If, on the other hand, I happen to switch branches before committing fileZ in the above example, I can just switch back and amend my last commit on the first branch. So yes, this is a feature, and it's a handy one. -- Andreas Ericsson andreas.ericsson@op5.se OP5 AB www.op5.se Tel: +46 8-230225 Fax: +46 8-230231 Considering the successes of the wars on alcohol, poverty, drugs and terror, I think we should give some serious thought to declaring war on peace. ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [BUG] git checkout <branch> allowed with uncommitted changes 2011-10-13 12:22 ` Andreas Ericsson @ 2011-10-13 13:09 ` arQon 2011-10-13 13:59 ` Carlos Martín Nieto 2011-10-13 13:58 ` [BUG] " arQon 1 sibling, 1 reply; 36+ messages in thread From: arQon @ 2011-10-13 13:09 UTC (permalink / raw) To: git Andreas Ericsson <ae <at> op5.se> writes: [snip] > This means that if fileX on branchA is different from fileX on branchB and you > *also* have local modifications to fileX, git will refuse to switch branches. > If, on the other hand branchA:fileX == branchB:fileX and you have modifications > to fileX in your work tree, there's no reason to refuse the branch change. There's an EXCELLENT reason to refuse the branch change: once it happens, what git is then telling is branchA, is not. > It's not a bug. You just read the manpage a bit wrong. [snip] > So yes, this is a feature, and it's a handy one. Thanks for the explanation. Unfortunately, I still can't see it as anything but a critical bug. Consider this: You're working on branchA and you have a bunch of uncommitted changes. You can't remember some detail of the bug you're fixing, so you switch branches to the master. You have to rebuild that branch, because your last build was from your branch. git now builds the master with sources that were NEVER committed to it. How is that not a total failure to maintain branch integrity? If that's the way git is, then that's how it is; and if there isn't a setting that can make it actually preserve branches properly, then there isn't. Which sucks for me, because an SCCS that lies about what branch you're "really" on is worse than useless, so I'm stuck with SVN. :( Thanks again for clearing it up for me though. ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [BUG] git checkout <branch> allowed with uncommitted changes 2011-10-13 13:09 ` arQon @ 2011-10-13 13:59 ` Carlos Martín Nieto 2011-10-13 17:09 ` [CLOSED] " arQon 0 siblings, 1 reply; 36+ messages in thread From: Carlos Martín Nieto @ 2011-10-13 13:59 UTC (permalink / raw) To: arQon; +Cc: git [-- Attachment #1: Type: text/plain, Size: 3195 bytes --] On Thu, 2011-10-13 at 13:09 +0000, arQon wrote: > Andreas Ericsson <ae <at> op5.se> writes: > [snip] > > This means that if fileX on branchA is different from fileX on branchB and you > > *also* have local modifications to fileX, git will refuse to switch branches. > > If, on the other hand branchA:fileX == branchB:fileX and you have modifications > > to fileX in your work tree, there's no reason to refuse the branch change. > > There's an EXCELLENT reason to refuse the branch change: once it happens, what > git is then telling is branchA, is not. When you changed branches, git told you that a file had been changed in the working tree. When you run 'git diff', it tells you the differences between what you have in your working tree and what's in the branch[0]. Git is trying hard not to loose your modifications (maybe it was a one-liner, maybe it was three hours of work) to the file. > > > It's not a bug. You just read the manpage a bit wrong. > [snip] > > So yes, this is a feature, and it's a handy one. > > Thanks for the explanation. Unfortunately, I still can't see it as anything but > a critical bug. Consider this: > > You're working on branchA and you have a bunch of uncommitted changes. > You can't remember some detail of the bug you're fixing, so you switch branches > to the master. You have to rebuild that branch, because your last build was from > your branch. git now builds the master with sources that were NEVER committed > to it. How is that not a total failure to maintain branch integrity? It sound like you've misunderstood what a branch is for git. A branch is only ever changed when you commit. What checkout does is change what the current branch is. For a case like what you describe, the developer would either do a temporary commit that they'd change later or stash the changes[1]. You could also use git-new-workdir (from contrib/) so you have two different directories that share the object storage. That has a few rough edges, but if you restrict it to a broken branch, you shouldn't have any problems. > > If that's the way git is, then that's how it is; and if there isn't a setting > that can make it actually preserve branches properly, then there isn't. Which > sucks for me, because an SCCS that lies about what branch you're "really" on > is worse than useless, so I'm stuck with SVN. :( Don't think of it as being "in" a branch. A checkout in git changes the active branch. If there are any files that are different between the two branches, they are changed. By switching branches with uncommitted changes, you're telling git that you would rather use the other branch to do your changes in. But git isn't doing this silently. After the checkout, it lists the files that have local modifications, so the developer can switch branches again and commit or stash the changes. cmn [0] Really it's between the working tree and the index, but since you just switched branches, the index is the same, and using it in that sentence would just cause confusion. [1] 'git stash' is a command that saves your uncommitted changes on a stack so you can recover them later. [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 490 bytes --] ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [CLOSED] git checkout <branch> allowed with uncommitted changes 2011-10-13 13:59 ` Carlos Martín Nieto @ 2011-10-13 17:09 ` arQon 2011-10-13 18:56 ` Alexey Shumkin 2011-10-13 19:01 ` Jakub Narebski 0 siblings, 2 replies; 36+ messages in thread From: arQon @ 2011-10-13 17:09 UTC (permalink / raw) To: git Carlos Martín Nieto <cmn <at> elego.de> writes: > When you changed branches, git told you that a file had been changed in > the working tree. That's a very good point, if it was actually documented at all that that's what it meant; and / or presented some warning that "BTW, if you edit this file again now, it'll screw up your whole tree" instead of an innocuous "M"; and didn't appear to contradict what the manpage says about "local modifications", we could probably have avoided half of this confusion. :P As it was, when I saw that M suddenly appear after several days of bouncing between branches without it and with everything working, I just thought "oh great, git's managed to break this tree", because I remembered the same thing from the previous trial run. That there IS an indication though might just be enough for me to be able to deal with it. Realistically, switching branches with uncommitted changes (unless you're doing it because you've ALREADY screwed up and are changing the wrong branch) is basically a trainwreck waiting to happen. git stash appears to be useless for any nontrivial change on the *other* branch, since there's no indication when you return to the stashed branch there's a stash sitting around, which is not something you're going to remember the next morning if fixing the master took the rest of the day, and you're not going to use "stash list" by then either. But as long as you get the "warning", an alias that does a "commit -am 'temp commit to avoid git breaking the tree'" is something I think I can probably live with. Thanks for all the help guys - very much appreciated. As far as I'm concerned, this topic's done. (Though if someone can come up with a script / hook / whatever that improves the "visibility" of stash, that would be awesome. Or one that makes the refusal to switch branches consistent). Looking at the manpage for checkout in the hope that there might be a "--safe" switch, I don't understand why "-f Proceed even if the index *or the working tree* differs from HEAD." even exists, since it proceeds under those conditions anyway. "--safe" appears to be exactly what the behavior should be if you DON'T specify -f, except that -f nukes the working tree outright rather than just bleeding it across. Hopefully it'll be clearer after some sleep. :) ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [CLOSED] git checkout <branch> allowed with uncommitted changes 2011-10-13 17:09 ` [CLOSED] " arQon @ 2011-10-13 18:56 ` Alexey Shumkin 2011-10-13 19:01 ` Jakub Narebski 1 sibling, 0 replies; 36+ messages in thread From: Alexey Shumkin @ 2011-10-13 18:56 UTC (permalink / raw) To: arQon; +Cc: git > (Though if someone can come up with a script / hook / whatever that > improves the "visibility" of stash, that would be awesome. > "git-completion" for Bash/ZSH gives such an opportunity I use it take a look into <git-sources>/contrib/completion/git-completion.bash -- >8 -- # 3) Consider changing your PS1 to also show the current branch: # Bash: PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ ' # ZSH: PS1='[%n@%m %c$(__git_ps1 " (%s)")]\$ ' # # The argument to __git_ps1 will be displayed only if you # are currently in a git repository. The %s token will be # the name of the current branch. # # In addition, if you set GIT_PS1_SHOWDIRTYSTATE to a nonempty # value, unstaged (*) and staged (+) changes will be shown next # to the branch name. You can configure this per-repository # with the bash.showDirtyState variable, which defaults to true # once GIT_PS1_SHOWDIRTYSTATE is enabled. # # You can also see if currently something is stashed, by setting # GIT_PS1_SHOWSTASHSTATE to a nonempty value. If something is stashed, # then a '$' will be shown next to the branch name. # # If you would like to see if there're untracked files, then you can # set GIT_PS1_SHOWUNTRACKEDFILES to a nonempty value. If there're # untracked files, then a '%' will be shown next to the branch name. # # If you would like to see the difference between HEAD and its # upstream, set GIT_PS1_SHOWUPSTREAM="auto". A "<" indicates # you are behind, ">" indicates you are ahead, and "<>" # indicates you have diverged. -- >8 -- my .bashrc contains (shortly) PS1='\[\e]0;\w [$(__git_ps1 "%s")]\a\]\n\[\e[32m\]\u@\h' PS1=$PS1' \[\e[33m\]\w\[\e[0m\]\n[$(__git_ps1 "%s")]\n\$' export PS1 export GIT_PS1_SHOWDIRTYSTATE=1 export GIT_PS1_SHOWSTASHSTATE=1 export GIT_PS1_SHOWUPSTREAM="auto" and console prompt with all possible cases looks like <username>@<hostname> ~/Git-src.git/contrib/completion [post-receive-email *+$>] $ * - I have unstaged changes + - I have staged changes $ - I have stashed changes (ta-daaa!) > - I have commits ahead upsteam (named branch I branched from) P.S. And JFYI, it is a good form in mailing lists to CC (Reply to all) participants ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [CLOSED] git checkout <branch> allowed with uncommitted changes 2011-10-13 17:09 ` [CLOSED] " arQon 2011-10-13 18:56 ` Alexey Shumkin @ 2011-10-13 19:01 ` Jakub Narebski 1 sibling, 0 replies; 36+ messages in thread From: Jakub Narebski @ 2011-10-13 19:01 UTC (permalink / raw) To: arQon; +Cc: git arQon <arqon@gmx.com> writes: > (Though if someone can come up with a script / hook / whatever that improves > the "visibility" of stash, that would be awesome. Or one that makes the > refusal to switch branches consistent). Well, if you use __git_ps1 from contrib/completion/git-completion.bash (installed with git-core package for some time), there is an option to add '$' to branch name if stash is non-empty (though it doesn't actually check if stash was on said branch). > Looking at the manpage for checkout in the hope that there might be a "--safe" > switch, I don't understand why > > "-f Proceed even if the index *or the working tree* differs from HEAD." > > even exists, since it proceeds under those conditions anyway. > "--safe" appears to be exactly what the behavior should be if you DON'T > specify -f, except that -f nukes the working tree outright rather than just > bleeding it across. Hopefully it'll be clearer after some sleep. :) Without '-f' git-checkout would switch branches only if uncomitted changes (which do not belong to any branch) could be "floated" on top of new branch. If branch you are switching to has differences from current branch that conflict with uncomitted changes, git would refuse switching branches. Now '-f' would get rid of your uncomitted changes, and '-m' try to merge it with changes brought by new branch. HTH -- Jakub Narębski ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [BUG] git checkout <branch> allowed with uncommitted changes 2011-10-13 12:22 ` Andreas Ericsson 2011-10-13 13:09 ` arQon @ 2011-10-13 13:58 ` arQon 2011-10-13 14:46 ` Carlos Martín Nieto 2011-10-13 16:08 ` Holger Hellmuth 1 sibling, 2 replies; 36+ messages in thread From: arQon @ 2011-10-13 13:58 UTC (permalink / raw) To: git Andreas Ericsson <ae <at> op5.se> writes: > there's no reason to refuse the branch change. > Partly because nothing will be lost Actually, this isn't true either, because of the second bug: doing a revert in branchA causes the changes in branchB to be lost. This can't possibly be the intended behavior: again, it completely violates the integrity of branches by allowing changes on one branch to impact a different branch. Your interpretation of the manpage doubtless matches the actual behavior of git, but I find it staggering if that truly is what was intended. It basically means that if you have local modifications, git will Break Your Entire Tree. That makes changing while you *do* have local mods more than a little undesirable, to put it mildly, which is something that a literal reading of the manpage would suggest is exactly what the "refuse to switch" is for. I guess only Linus knows what he actually meant. :) Anyway, I guess it's all moot: call it a feature or call it a bug, this cross- branch destruction is a deal-breaker for me, especially given the bug above that actually loses data outright, rather than "only" putting multiple branches into an incorrect state. Thanks for your time and help. ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [BUG] git checkout <branch> allowed with uncommitted changes 2011-10-13 13:58 ` [BUG] " arQon @ 2011-10-13 14:46 ` Carlos Martín Nieto 2011-10-13 15:53 ` arQon 2011-10-13 16:08 ` Holger Hellmuth 1 sibling, 1 reply; 36+ messages in thread From: Carlos Martín Nieto @ 2011-10-13 14:46 UTC (permalink / raw) To: arQon; +Cc: git [-- Attachment #1: Type: text/plain, Size: 2570 bytes --] On Thu, 2011-10-13 at 13:58 +0000, arQon wrote: > Andreas Ericsson <ae <at> op5.se> writes: > > there's no reason to refuse the branch change. > > Partly because nothing will be lost > > Actually, this isn't true either, because of the second bug: doing a revert > in branchA causes the changes in branchB to be lost. This can't possibly be > the intended behavior: again, it completely violates the integrity of branches > by allowing changes on one branch to impact a different branch. I have not seen a revert command in any of your messages. If a revert on one branch changes another one, that would be a bug, but you haven't shown this to happen. > > Your interpretation of the manpage doubtless matches the actual behavior of git, > but I find it staggering if that truly is what was intended. It basically means > that if you have local modifications, git will Break Your Entire Tree. That > makes changing while you *do* have local mods more than a little undesirable, > to put it mildly, which is something that a literal reading of the manpage would > suggest is exactly what the "refuse to switch" is for. I guess only Linus knows > what he actually meant. :) Do not confuse a branch with a worktree. If you haven't committed yet, those changes aren't in the branch (just like they wouldn't be in svn) > > Anyway, I guess it's all moot: call it a feature or call it a bug, this cross- > branch destruction is a deal-breaker for me, especially given the bug above that > actually loses data outright, rather than "only" putting multiple branches into > an incorrect state. I've just asked some subversion developers to confirm this, and then tried it out myself: Subversion (my locally-installed version is 1.6.17, latest stable) behaves the same way. Local modifications are carried over across branches. $ svn copy ^/trunk ^/branches/somebranch # Create a new branch $ $EDITOR somefile # which exists in trunk and somebranch $ svn switch ^/branches/somebranch $ svn diff # My local changes are there! The reason this happens both in svn and git is that the most likely cause for someone to change a branch mid-edit is that they decide they're doing the changes on the wrong branch. What I did notice is that svn doesn't tell you about the modifications being carried over (presumably you're meant to use status and diff to figure out what's going on). Therefore, the same workflow (with the only difference being how to create and switch branches) works for svn and git in this case. cmn [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 490 bytes --] ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [BUG] git checkout <branch> allowed with uncommitted changes 2011-10-13 14:46 ` Carlos Martín Nieto @ 2011-10-13 15:53 ` arQon 2011-10-13 16:17 ` Alexey Shumkin ` (4 more replies) 0 siblings, 5 replies; 36+ messages in thread From: arQon @ 2011-10-13 15:53 UTC (permalink / raw) To: git Carlos Martín Nieto <cmn <at> elego.de> writes: > I have not seen a revert command in any of your messages. If a revert on > one branch changes another one, that would be a bug, but you haven't > shown this to happen. Sorry, it was in prose in the original post (near the end) "At this point, reverting the master with "checkout --" also wipes out the changes on the other branch. It's like the merge symlinked the two branches rather than, well, merging them." Based on the explanations here, and the git *st* message, it wiping out the other branch is to be expected, because it's "the working directory", not "the branch". >git st # On branch foo # 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: file1.txt # no changes added to commit (use "git add" and/or "git commit -a") What makes this really interesting though is this: I tried to switch to master to see if that gave the same warning, and NOW, I get the correct error. >git co master error: Your local changes to the following files would be overwritten by checkout: file1.txt Please, commit your changes or stash them before you can switch branches. Aborting I'm sure if I thought about it enough (ie re-read Andreas's post a couple more times) I'd be able to understand why git gets it right sometimes but not other times, but I'm too tired right now. Even when I *am* awake and grok it properly, I'm still going to be annoyed that it's so inconsistent, but I can live with that if I have to. > The reason this happens both in svn and git is that the most likely > cause for someone to change a branch mid-edit is that they decide > they're doing the changes on the wrong branch. Lucky you. :P The most likely reason for me is, I'm working on something and I get interrupted and have to switch. Since the code may well not even compile at this point, the last thing I want to do is commit it. git's ability for that commit to be local is half the reason I'm trying to switch to it. (I'm not particularly keen on having to commit broken code to even a local repo, but that's still a hell of a lot better than having it pushed upstream as well). > svn doesn't tell you about the modifications being carried over > (presumably you're meant to use status and diff to figure out what's > going on). Therefore, the same workflow (with the only difference being > how to create and switch branches) works for svn and git in this case. I expect part of my confusion comes from using different workdirs for svn branches, ie "clone" rather than "branch", because branching in svn is such a PITA I just don't bother with it unless the branch is going to be "heavyweight" enough to warrant a "proper" branch. Good to be reminded of though, thanks. ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [BUG] git checkout <branch> allowed with uncommitted changes 2011-10-13 15:53 ` arQon @ 2011-10-13 16:17 ` Alexey Shumkin 2011-10-14 6:51 ` Alexey Shumkin 2011-10-13 16:32 ` Holger Hellmuth ` (3 subsequent siblings) 4 siblings, 1 reply; 36+ messages in thread From: Alexey Shumkin @ 2011-10-13 16:17 UTC (permalink / raw) To: arQon; +Cc: git > Lucky you. :P The most likely reason for me is, I'm working on > something and I get interrupted and have to switch. Since the code > may well not even compile at this point, the last thing I want to do > is commit it. "git stash" helps here With Git you can/have_to/must change your SVN-based habits. DO NOT BE AFRAID OF FREQUENT COMMITS! There are local until you push them. >git's ability for that commit to be local is half the > reason I'm trying to switch to it. You always have a chance to modify/reedit you commits see "git commit --amend" and "git rebase [-i]" I'm telling you it as an ex-SVN user. >(I'm not particularly keen on > having to commit broken code to even a local repo, but that's still a > hell of a lot better than having it pushed upstream as well). Again, do not be afraid to commit your changes. Be afraid of losing your changes. Git makes everything (as other discussion participants already described) to keep your changes within workflow when you switch between branches often. Read some books which are describe Git's usual (and effective) workflow, ProGit - http://progit.org/book/ Version Contol by Example (there is a chapter about Git) - http://git-scm.com/course/svn.html Hope, you'll feel the power of Git )) ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [BUG] git checkout <branch> allowed with uncommitted changes 2011-10-13 16:17 ` Alexey Shumkin @ 2011-10-14 6:51 ` Alexey Shumkin 0 siblings, 0 replies; 36+ messages in thread From: Alexey Shumkin @ 2011-10-14 6:51 UTC (permalink / raw) To: arQon; +Cc: git > > Lucky you. :P The most likely reason for me is, I'm working on > > something and I get interrupted and have to switch. Since the code > > may well not even compile at this point, the last thing I want to do > > is commit it. > "git stash" helps here > With Git you can/have_to/must change your SVN-based habits. > DO NOT BE AFRAID OF FREQUENT COMMITS! > There are local until you push them. > > >git's ability for that commit to be local is half the > > reason I'm trying to switch to it. > You always have a chance to modify/reedit you commits > see "git commit --amend" and "git rebase [-i]" > > I'm telling you it as an ex-SVN user. > >(I'm not particularly keen on > > having to commit broken code to even a local repo, but that's still > > a hell of a lot better than having it pushed upstream as well). > > Again, do not be afraid to commit your changes. Be afraid of losing > your changes. Git makes everything (as other discussion participants > already described) to keep your changes within workflow when you > switch between branches often. > > Read some books which are describe Git's usual (and effective) > workflow, ProGit - http://progit.org/book/ > Version Contol by Example (there is a chapter about Git) - > http://git-scm.com/course/svn.html oops, wrong url fixed link Version Contol by Example (there is a chapter about Git) - http://www.ericsink.com/vcbe/ ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [BUG] git checkout <branch> allowed with uncommitted changes 2011-10-13 15:53 ` arQon 2011-10-13 16:17 ` Alexey Shumkin @ 2011-10-13 16:32 ` Holger Hellmuth 2011-10-13 17:04 ` Carlos Martín Nieto ` (2 subsequent siblings) 4 siblings, 0 replies; 36+ messages in thread From: Holger Hellmuth @ 2011-10-13 16:32 UTC (permalink / raw) To: arQon; +Cc: git On 13.10.2011 17:53, arQon wrote: >> git st > # On branch foo > # 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: file1.txt > # > no changes added to commit (use "git add" and/or "git commit -a") > > What makes this really interesting though is this: I tried to switch to > master to see if that gave the same warning, and NOW, I get the correct > error. > >> git co master > error: Your local changes to the following files would be overwritten by > checkout: > file1.txt > Please, commit your changes or stash them before you can switch branches. > Aborting At the end of your example (in a previous email) you were on branch master, now in the beginning you are on foo. So you at least changed branch again inbetween. maybe you also committed something? Check out git log or gitk I tried your example and I can checkout master and foo again and again and I never see the error message. > Lucky you. :P The most likely reason for me is, I'm working on something > and I get interrupted and have to switch. Since the code may well not even > compile at this point, the last thing I want to do is commit it. git's > ability for that commit to be local is half the reason I'm trying to switch > to it. (I'm not particularly keen on having to commit broken code to even a > local repo, but that's still a hell of a lot better than having it pushed > upstream as well). As Alexey already said, just commit and later amend. Or stash. Git encourages you to commit small changes you can put a name to. You never should delay a commit because it produces unworkable code. Instead have a master branch (or branches) that always compiles and branches for the unfinished stuff. Then it won't matter if some branch is only half working. ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [BUG] git checkout <branch> allowed with uncommitted changes 2011-10-13 15:53 ` arQon 2011-10-13 16:17 ` Alexey Shumkin 2011-10-13 16:32 ` Holger Hellmuth @ 2011-10-13 17:04 ` Carlos Martín Nieto 2011-10-13 18:19 ` arQon 2011-10-13 17:06 ` Sergei Organov 2011-10-13 19:44 ` PJ Weisberg 4 siblings, 1 reply; 36+ messages in thread From: Carlos Martín Nieto @ 2011-10-13 17:04 UTC (permalink / raw) To: arQon; +Cc: git [-- Attachment #1: Type: text/plain, Size: 4828 bytes --] On Thu, 2011-10-13 at 15:53 +0000, arQon wrote: > Carlos Martín Nieto <cmn <at> elego.de> writes: > > I have not seen a revert command in any of your messages. If a revert on > > one branch changes another one, that would be a bug, but you haven't > > shown this to happen. > > Sorry, it was in prose in the original post (near the end) > "At this point, reverting the master with "checkout --" also wipes out the > changes on the other branch. It's like the merge symlinked the two branches > rather than, well, merging them." > > Based on the explanations here, and the git *st* message, it wiping out the > other branch is to be expected, because it's "the working directory", not > "the branch". > > >git st > # On branch foo > # 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: file1.txt > # > no changes added to commit (use "git add" and/or "git commit -a") > > What makes this really interesting though is this: I tried to switch to > master to see if that gave the same warning, and NOW, I get the correct > error. > > >git co master > error: Your local changes to the following files would be overwritten by > checkout: > file1.txt > Please, commit your changes or stash them before you can switch branches. > Aborting > > I'm sure if I thought about it enough (ie re-read Andreas's post a couple > more times) I'd be able to understand why git gets it right sometimes but > not other times, but I'm too tired right now. Even when I *am* awake and > grok it properly, I'm still going to be annoyed that it's so inconsistent, > but I can live with that if I have to. If file1.txt in the foo branch is different from the one in the master branch, git will refuse to switch branches. 'git diff foo master' should show that those two files are different. > > > The reason this happens both in svn and git is that the most likely > > cause for someone to change a branch mid-edit is that they decide > > they're doing the changes on the wrong branch. > > Lucky you. :P The most likely reason for me is, I'm working on something > and I get interrupted and have to switch. Since the code may well not even > compile at this point, the last thing I want to do is commit it. git's > ability for that commit to be local is half the reason I'm trying to switch > to it. (I'm not particularly keen on having to commit broken code to even a > local repo, but that's still a hell of a lot better than having it pushed > upstream as well). Yes, this is a great feature of distributed systems. A local repo is where you experiment. Treat it as your own personal space to play around with things. Committing non-working code is fine, as long as you don't push it out. > > > svn doesn't tell you about the modifications being carried over > > (presumably you're meant to use status and diff to figure out what's > > going on). Therefore, the same workflow (with the only difference being > > how to create and switch branches) works for svn and git in this case. > > I expect part of my confusion comes from using different workdirs for svn > branches, ie "clone" rather than "branch", because branching in svn is such > a PITA I just don't bother with it unless the branch is going to be > "heavyweight" enough to warrant a "proper" branch. Then the issue is that you've changed the workflow but haven't adjusted for it. You can do this as well with the git-new-workdir. As I mentioned it has a few rough edges, but if you're going to use it to have a checkout of a particular branch, it shouldn't present any problems. That would be like your current workflow. Another option is to clone with a reference which will create a brand new clone but will use the objects that you've already downloaded (or just clone locally). This can be more comfortable than using the new-workdir and will hardly put any strain on the filesystem. The bigger problem seems to be your reluctance to accept that git is different from subversion, as you keep saying "that's just how git is" to back your claim that you can't trust git on a feature where subversion behaves the same way. If you'd rather use different directories for different branches, you can. That is not an aspect which you can point to and say that you can't migrate to git for that reason. If you're more comfortable with subversion, that's fine also, it's an excellent piece of software[0], but don't go around saying that git corrupts branches when that's blatantly not true. cmn [0] Whatever one may think about the merits of CVCS vs DVCS; that shouldn't come into the quality of the software. [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 490 bytes --] ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [BUG] git checkout <branch> allowed with uncommitted changes 2011-10-13 17:04 ` Carlos Martín Nieto @ 2011-10-13 18:19 ` arQon 2011-10-13 18:28 ` Junio C Hamano 2011-10-13 20:07 ` Carlos Martín Nieto 0 siblings, 2 replies; 36+ messages in thread From: arQon @ 2011-10-13 18:19 UTC (permalink / raw) To: git Carlos Martín Nieto <cmn <at> elego.de> writes: > If file1.txt in the foo branch is different from the one in the master > branch, git will refuse to switch branches. 'git diff foo master' should > show that those two files are different. Right, but only for a definition of "branch" that is actually "a fully committed branch", hence the confusion and the mention of "uncommitted changes" in the topic. An expectation that "co branch" should be analogous to "cd ../branch/" is by no means unreasonable. YOU may know better, but it's surprisingly non-obvious, especially considering the -f option on checkout and the wording of -m, both of which strongly suggest that, in the absence of either of those flags, git WILL preserve the worktree by refusing to switch until that potentially- harmful situation is resolved by the user. > Committing non-working code is fine, as long as you don't push it out. Right, but for the problem I was describing it's actually "committing non-working code is a requirement, in this situation, if you don't want your tree to get eaten". Going from "you absolutely must not do this" to "you must do this" takes some mental adjustment, but you also have to be *aware* that you now have to do something that was previously prohibited, which I wasn't. > The bigger problem seems to be your reluctance to accept that git is > different from subversion Not at all. If I didn't WANT something different, I wouldn't have been trying to move to git in the first place. :) > but don't go around saying that git > corrupts branches when that's blatantly not true. See my first para in this post (or indeed, the original post). It's "not true" provided all branches are fully committed when you switch between them. It blatantly IS true if you switch from a dirty branch. Redefining "branch" to mean "fully committed branch" makes it "not true" in that context, but so does redefining green to be red and saying that grass is red in that context: it may be correct from a certain POV, but it's incomprehensible to anyone who isn't aware of that semantic change. Anyway, I think we're done with this thread. Thanks for your (key) observation earlier and several clarifications, and hopefully this will help the next guy who runs into this problem and gets confused like I did. :) ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [BUG] git checkout <branch> allowed with uncommitted changes 2011-10-13 18:19 ` arQon @ 2011-10-13 18:28 ` Junio C Hamano 2011-10-13 18:56 ` arQon 2011-10-13 20:07 ` Carlos Martín Nieto 1 sibling, 1 reply; 36+ messages in thread From: Junio C Hamano @ 2011-10-13 18:28 UTC (permalink / raw) To: arQon; +Cc: git arQon <arqon@gmx.com> writes: > ..., in the absence of either of those flags, git > WILL preserve the worktree by refusing to switch until that potentially- > harmful situation is resolved by the user. Perhaps you can prepare a documentation patch to make it clear that git WILL preserve the LOCAL CHANGES to the working tree? As it would already be clear to anybody reading this thread so far, local changes made to the working tree do not belong to any particular branch. They are floating on top, and it is up to the user what to do with these floating changes when they conflict with the differences between the branches you are switching across (i.e. you cannot switch so you need to clean up by either committing, stashing, or deciding not to switch and instead complete the work before you switch), and when they do not conflict with the differences between the branches you are switching across (i.e. you will carry them to the new working tree. It may be that you made these changes and then realized that they do not belong to the goal the current branch aims to achieve and that is why you decided to switch to another branch, in which case you do not have to do anything special in order to continue to work and complete it to commit to the switched branch. It may be that you made these changes but needed to tend to unrelated business on an unrelated branch and that is why you switched, in which case you would want to clear them away, which is exactly what stash was invented for). ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [BUG] git checkout <branch> allowed with uncommitted changes 2011-10-13 18:28 ` Junio C Hamano @ 2011-10-13 18:56 ` arQon 2011-10-14 1:38 ` Jeff King 0 siblings, 1 reply; 36+ messages in thread From: arQon @ 2011-10-13 18:56 UTC (permalink / raw) To: git Junio C Hamano <gitster <at> pobox.com> writes: > Perhaps you can prepare a documentation patch to make it clear that git > WILL preserve the LOCAL CHANGES to the working tree? Or to put that another way, git WILL NOT "rewind" those local changes when switching branches (which I still think is the more common case for new users than failing to branch before editing files). Or refuse to switch if you have some. Except for when it does. I'll give a shot, though I don't know how good it'll be. Off the top of my head, I don't see any good way to explain the inconsistency with LOCAL CHANGES sometimes preventing switches and sometimes not, based on what is to the user an arbitrary set of rules that has nothing to do with the *current state* of the worktree, but rather the state of those files in prior commits. But sure, I'll see if I can come up with something. If nothing else, having the manpage at least explain what "M" means; that it can be potentially disastrous; and what you need to do to avoid it, would be a definite plus. ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [BUG] git checkout <branch> allowed with uncommitted changes 2011-10-13 18:56 ` arQon @ 2011-10-14 1:38 ` Jeff King 2011-10-14 9:27 ` Holger Hellmuth 0 siblings, 1 reply; 36+ messages in thread From: Jeff King @ 2011-10-14 1:38 UTC (permalink / raw) To: arQon; +Cc: git On Thu, Oct 13, 2011 at 06:56:14PM +0000, arQon wrote: > I'll give a shot, though I don't know how good it'll be. Off the top of my > head, I don't see any good way to explain the inconsistency with LOCAL CHANGES > sometimes preventing switches and sometimes not, based on what is to the user > an arbitrary set of rules that has nothing to do with the *current state* of > the worktree, but rather the state of those files in prior commits. The rules are fairly straightforward. You are moving from branch A to branch B. If path X is not changed going from A to B, git will not touch it, whether or not you have local changes. If path X is changed going from A to B, then git will refuse the checkout, and you have the option of: 1. checkout -f: overwrite your local changes with what's in B 2. checkout -m: merge your changes with what's in B (using A as a common ancestor) > But sure, I'll see if I can come up with something. If nothing else, > having the manpage at least explain what "M" means; that it can be > potentially disastrous; and what you need to do to avoid it, would be > a definite plus. You keep saying things like "disastrous". Git's rules are specifically designed to be as flexible as possible without allowing the checkout command to cause data loss. Do you actually have a case that causes irrecoverable data loss? Note that I don't count "these changes were based on A, now they are based on B" as data loss. Your file content is still completely intact, and if you want to make them based on "A" again, you just need to "git checkout A" again. -Peff ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [BUG] git checkout <branch> allowed with uncommitted changes 2011-10-14 1:38 ` Jeff King @ 2011-10-14 9:27 ` Holger Hellmuth 2011-10-14 9:54 ` Victor Engmark 0 siblings, 1 reply; 36+ messages in thread From: Holger Hellmuth @ 2011-10-14 9:27 UTC (permalink / raw) To: Jeff King; +Cc: arQon, git On 14.10.2011 03:38, Jeff King wrote: > On Thu, Oct 13, 2011 at 06:56:14PM +0000, arQon wrote: > >> I'll give a shot, though I don't know how good it'll be. Off the top of my >> head, I don't see any good way to explain the inconsistency with LOCAL CHANGES >> sometimes preventing switches and sometimes not, based on what is to the user >> an arbitrary set of rules that has nothing to do with the *current state* of >> the worktree, but rather the state of those files in prior commits. > > The rules are fairly straightforward. They are. But what arQon is getting at is that the normal switchability depends on something that is often a game of chance: Did I change a file that is different between the two branches? That is only known by the user for branches not far removed. Now the obvious answer is: It doesn't matter because git tells you. At the right time to act upon it. But git says "M file" instead of what 'git status' would say: "# modified: file". Is there a reason for that? On one hand it should be familiar to svn users, on the other hand it is an inconsistency. And personally I always hated those cryptic status flags of svn Another good point arQon made is that the case that you switched with forgotten local changes is more common than the case that you switched because you made changes in the wrong branch. If that were the case the warning that you have local changes should be more visible than that small "M file", at best something that looks similar to 'git status' output. Now what really is more common depends on the individual. If you are a beginner or a semi-frequent user, then forgetting local changes is probably far more common, wheras most people on this mailing list would say its the other way round. It much depends on your commit frequency because the more often you commit, the less likely is that you would forget local changes. ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [BUG] git checkout <branch> allowed with uncommitted changes 2011-10-14 9:27 ` Holger Hellmuth @ 2011-10-14 9:54 ` Victor Engmark 2011-10-16 18:25 ` arQon 0 siblings, 1 reply; 36+ messages in thread From: Victor Engmark @ 2011-10-14 9:54 UTC (permalink / raw) To: Holger Hellmuth; +Cc: Jeff King, arQon, git On Fri, Oct 14, 2011 at 11:27:47AM +0200, Holger Hellmuth wrote: > On 14.10.2011 03:38, Jeff King wrote: > >On Thu, Oct 13, 2011 at 06:56:14PM +0000, arQon wrote: > > > >>I'll give a shot, though I don't know how good it'll be. Off the top of my > >>head, I don't see any good way to explain the inconsistency with LOCAL CHANGES > >>sometimes preventing switches and sometimes not, based on what is to the user > >>an arbitrary set of rules that has nothing to do with the *current state* of > >>the worktree, but rather the state of those files in prior commits. > > > >The rules are fairly straightforward. > > They are. But what arQon is getting at is that the normal > switchability depends on something that is often a game of chance: > Did I change a file that is different between the two branches? That > is only known by the user for branches not far removed. > > Now the obvious answer is: It doesn't matter because git tells you. > At the right time to act upon it. But git says "M file" instead of > what 'git status' would say: "# modified: file". Is there a > reason for that? On one hand it should be familiar to svn users, on > the other hand it is an inconsistency. And personally I always hated > those cryptic status flags of svn > > Another good point arQon made is that the case that you switched > with forgotten local changes is more common than the case that you > switched because you made changes in the wrong branch. If that were > the case the warning that you have local changes should be more > visible than that small "M file", at best something that looks > similar to 'git status' output. Very good point. How about by default just running `git status` after a successful checkout, and only printing the result if there are any changes? That way: 1) If no changes are pending, nothing is displayed. 2) The user sees a *familiar* style output if anything changed. 3) If there's an alias for "status", it would be used. Example: $ mkdir /tmp/test $ cd /tmp/test $ git init Initialized empty Git repository in /tmp/test/.git/ $ echo foo > foo $ echo bar > bar $ git add foo bar $ git commit -m "Initial commit" [master (root-commit) 55246c6] Initial commit 2 files changed, 2 insertions(+), 0 deletions(-) create mode 100644 bar create mode 100644 foo $ echo foobar > bar $ git branch --track test Branch test set up to track local branch master. $ git checkout test M bar Switched to branch 'test' After `git checkout test`, we should instead see: # On branch test # Changed but not updated: # (use "git add <file>..." to update what will be committed) # (use "git checkout -- <file>..." to discard changes in working directory) # # modified: bar # no changes added to commit (use "git add" and/or "git commit -a") 2c, V -- terreActive AG Kasinostrasse 30 CH-5001 Aarau Tel: +41 62 834 00 55 Fax: +41 62 823 93 56 www.terreactive.ch Wir sichern Ihren Erfolg - seit 15 Jahren ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [BUG] git checkout <branch> allowed with uncommitted changes 2011-10-14 9:54 ` Victor Engmark @ 2011-10-16 18:25 ` arQon 2011-10-16 20:37 ` Junio C Hamano 0 siblings, 1 reply; 36+ messages in thread From: arQon @ 2011-10-16 18:25 UTC (permalink / raw) To: git Victor Engmark <victor.engmark <at> terreactive.ch> writes: > Very good point. How about by default just running `git status` after a > successful checkout, and only printing the result if there are any > changes? That way: > 1) If no changes are pending, nothing is displayed. > 2) The user sees a *familiar* style output if anything changed. > 3) If there's an alias for "status", it would be used. I'm sold on this. Better documentation for checkout wouldn't hurt regardless, and I'm still planning on that when I get a chance; but better *behavior* is a clear win either way. Adding half a page of text to the docs explaining what each status char means is a hugely-inferior "solution" to simply not having an aberrant status-ish output in the first place. ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [BUG] git checkout <branch> allowed with uncommitted changes 2011-10-16 18:25 ` arQon @ 2011-10-16 20:37 ` Junio C Hamano 2011-10-16 22:04 ` Holger Hellmuth 0 siblings, 1 reply; 36+ messages in thread From: Junio C Hamano @ 2011-10-16 20:37 UTC (permalink / raw) To: arQon; +Cc: git arQon <arqon@gmx.com> writes: > ... better *behavior* is a > clear win either way. I doubt the full status output is better behaviour. For one thing, you do not need full status as by definition branch switching would only have local changes as a result (i.e. you will not see "Changes to be committed" section). But if you really do not want to learn how to read "diff --name-status" output, here is a patch to allow you say "git checkout -v other_branch". Hopefully it will help you convince yourself why it is not a better behaviour. builtin/checkout.c | 46 +++++++++++++++++++++++++++++++++------------- 1 files changed, 33 insertions(+), 13 deletions(-) diff --git a/builtin/checkout.c b/builtin/checkout.c index 49a547a..0c21556 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -28,7 +28,7 @@ static const char * const checkout_usage[] = { }; struct checkout_opts { - int quiet; + int verbosity; int merge; int force; int force_detach; @@ -291,10 +291,10 @@ static int checkout_paths(struct tree *source_tree, const char **pathspec, return errs; } -static void show_local_changes(struct object *head, struct diff_options *opts) +static void show_local_changes_brief(struct object *head, struct diff_options *opts) { struct rev_info rev; - /* I think we want full paths, even if we're in a subdirectory. */ + init_revisions(&rev, NULL); rev.diffopt.flags = opts->flags; rev.diffopt.output_format |= DIFF_FORMAT_NAME_STATUS; @@ -304,6 +304,26 @@ static void show_local_changes(struct object *head, struct diff_options *opts) run_diff_index(&rev, 0); } +static void show_local_changes_status(void) +{ + const char *argv[] = { "status", NULL }; + + run_command_v_opt(argv, RUN_GIT_CMD); +} + +static void show_local_changes(struct checkout_opts *opts, + struct object *head, + struct diff_options *diffopts) +{ + if (opts->force || opts->verbosity < 0) + return; + + if (0 < opts->verbosity) + show_local_changes_status(); + else + show_local_changes_brief(head, diffopts); +} + static void describe_detached_head(const char *msg, struct commit *commit) { struct strbuf sb = STRBUF_INIT; @@ -326,7 +346,7 @@ static int reset_tree(struct tree *tree, struct checkout_opts *o, int worktree) opts.reset = 1; opts.merge = 1; opts.fn = oneway_merge; - opts.verbose_update = !o->quiet; + opts.verbose_update = (0 <= o->verbosity); opts.src_index = &the_index; opts.dst_index = &the_index; parse_tree(tree); @@ -403,7 +423,7 @@ static int merge_working_tree(struct checkout_opts *opts, topts.update = 1; topts.merge = 1; topts.gently = opts->merge && old->commit; - topts.verbose_update = !opts->quiet; + topts.verbose_update = (0 <= opts->verbosity); topts.fn = twoway_merge; topts.dir = xcalloc(1, sizeof(*topts.dir)); topts.dir->flags |= DIR_SHOW_IGNORED; @@ -478,9 +498,6 @@ static int merge_working_tree(struct checkout_opts *opts, commit_locked_index(lock_file)) die(_("unable to write new index file")); - if (!opts->force && !opts->quiet) - show_local_changes(&new->commit->object, &opts->diff_options); - return 0; } @@ -552,14 +569,14 @@ static void update_refs_for_switch(struct checkout_opts *opts, } else if (opts->force_detach || !new->path) { /* No longer on any branch. */ update_ref(msg.buf, "HEAD", new->commit->object.sha1, NULL, REF_NODEREF, DIE_ON_ERR); - if (!opts->quiet) { + if (0 <= opts->verbosity) { if (old->path && advice_detached_head) detach_advice(old->path, new->name); describe_detached_head(_("HEAD is now at"), new->commit); } } else if (new->path) { /* Switch branches. */ create_symref("HEAD", new->path, msg.buf); - if (!opts->quiet) { + if (0 <= opts->verbosity) { if (old->path && !strcmp(new->path, old->path)) { fprintf(stderr, _("Already on '%s'\n"), new->name); @@ -584,7 +601,7 @@ static void update_refs_for_switch(struct checkout_opts *opts, } remove_branch_state(); strbuf_release(&msg); - if (!opts->quiet && + if (0 <= opts->verbosity && (new->path || (!opts->force_detach && !strcmp(new->name, "HEAD")))) report_tracking(new); } @@ -717,13 +734,16 @@ static int switch_branches(struct checkout_opts *opts, struct branch_info *new) if (ret) return ret; - if (!opts->quiet && !old.path && old.commit && new->commit != old.commit) + if (0 <= opts->verbosity && !old.path && old.commit && new->commit != old.commit) orphaned_commit_warning(old.commit); update_refs_for_switch(opts, &old, new); ret = post_checkout_hook(old.commit, new->commit, 1); free((char *)old.path); + + show_local_changes(opts, &new->commit->object, &opts->diff_options); + return ret || opts->writeout_error; } @@ -906,7 +926,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) int patch_mode = 0; int dwim_new_local_branch = 1; struct option options[] = { - OPT__QUIET(&opts.quiet, "suppress progress reporting"), + OPT__VERBOSITY(&opts.verbosity), OPT_STRING('b', NULL, &opts.new_branch, "branch", "create and checkout a new branch"), OPT_STRING('B', NULL, &opts.new_branch_force, "branch", ^ permalink raw reply related [flat|nested] 36+ messages in thread
* Re: [BUG] git checkout <branch> allowed with uncommitted changes 2011-10-16 20:37 ` Junio C Hamano @ 2011-10-16 22:04 ` Holger Hellmuth 0 siblings, 0 replies; 36+ messages in thread From: Holger Hellmuth @ 2011-10-16 22:04 UTC (permalink / raw) To: Junio C Hamano; +Cc: arQon, git Am 16.10.2011 22:37, schrieb Junio C Hamano: > I doubt the full status output is better behaviour. For one thing, you do > not need full status as by definition branch switching would only have > local changes as a result (i.e. you will not see "Changes to be committed" > section). ?? After "git add" on a changed file I see it under "Changes to be committed". And branch switching still works (with newest git from master branch): # On branch two # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: test1.txt # # 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: test2.txt # Small inconsistency: On the other branch instead of "Changes not staged for commit:" the text "Changed but not updated:" is printed, everything else is unchanged ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [BUG] git checkout <branch> allowed with uncommitted changes 2011-10-13 18:19 ` arQon 2011-10-13 18:28 ` Junio C Hamano @ 2011-10-13 20:07 ` Carlos Martín Nieto 1 sibling, 0 replies; 36+ messages in thread From: Carlos Martín Nieto @ 2011-10-13 20:07 UTC (permalink / raw) To: arQon; +Cc: git [-- Attachment #1: Type: text/plain, Size: 3810 bytes --] On Thu, 2011-10-13 at 18:19 +0000, arQon wrote: > Carlos Martín Nieto <cmn <at> elego.de> writes: > > If file1.txt in the foo branch is different from the one in the master > > branch, git will refuse to switch branches. 'git diff foo master' should > > show that those two files are different. > > Right, but only for a definition of "branch" that is actually "a fully > committed branch", hence the confusion and the mention of "uncommitted > changes" in the topic. I'm not aware of any other definition of a branch, either for git or subversion. > > An expectation that "co branch" should be analogous to "cd ../branch/" is by > no means unreasonable. YOU may know better, but it's surprisingly non-obvious, I don't see how. Switching branches is not the same as changing directories. It doesn't work that way, neither with git nor subversion. If you choose to have each branch in their own directory, that's fine, but it has very little to do with the VCS tool. > especially considering the -f option on checkout and the wording of -m, both > of which strongly suggest that, in the absence of either of those flags, git > WILL preserve the worktree by refusing to switch until that potentially- > harmful situation is resolved by the user. The general description could probably benefit from a more explicit mention of what happens if there are local modifications. Currently it looks like it's only mentioned in the text of -f and -m, which is not particularly helpful. > > > Committing non-working code is fine, as long as you don't push it out. > > Right, but for the problem I was describing it's actually "committing > non-working code is a requirement, in this situation, if you don't want your > tree to get eaten". Going from "you absolutely must not do this" to "you must > do this" takes some mental adjustment, but you also have to be *aware* that > you now have to do something that was previously prohibited, which I wasn't. You can also have a different directory for the other branch if you really don't want to commit until it works. This is the same situation that you find yourself right now with subversion; I don't see how it's that hard to recognise that. > > > The bigger problem seems to be your reluctance to accept that git is > > different from subversion > > Not at all. If I didn't WANT something different, I wouldn't have been trying > to move to git in the first place. :) > > > but don't go around saying that git > > corrupts branches when that's blatantly not true. > > See my first para in this post (or indeed, the original post). It's "not true" > provided all branches are fully committed when you switch between them. Right. > It blatantly IS true if you switch from a dirty branch. No. The branch has not been corrupted or changed at all. Your local modifications to files in the working tree were kept. Again, this happens both for git and svn. > Redefining "branch" to mean "fully committed branch" makes it "not true" in > that context, but so does redefining green to be red and saying that grass is > red in that context: it may be correct from a certain POV, but it's > incomprehensible to anyone who isn't aware of that semantic change. This smells like FUD. A branch and a directory are two different things. If you find it more comfortable to use different directories for different branches that's fine, but that doesn't make it a branch. Changing a file doesn't automatically mean that that version of the file belongs to the currently active branch (or URL in the case for svn). A branch is only ever changed when you commit. This is something that holds true across VCSs. Play with subversion's 'switch' command, it behaves the same way. cmn [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 490 bytes --] ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [BUG] git checkout <branch> allowed with uncommitted changes 2011-10-13 15:53 ` arQon ` (2 preceding siblings ...) 2011-10-13 17:04 ` Carlos Martín Nieto @ 2011-10-13 17:06 ` Sergei Organov 2011-10-13 19:44 ` PJ Weisberg 4 siblings, 0 replies; 36+ messages in thread From: Sergei Organov @ 2011-10-13 17:06 UTC (permalink / raw) To: arQon; +Cc: git arQon <arqon@gmx.com> writes: [...] > Lucky you. :P The most likely reason for me is, I'm working on something > and I get interrupted and have to switch. Since the code may well not even > compile at this point, the last thing I want to do is commit it. 'git stash' is exactly what you need then. -- Sergei. ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [BUG] git checkout <branch> allowed with uncommitted changes 2011-10-13 15:53 ` arQon ` (3 preceding siblings ...) 2011-10-13 17:06 ` Sergei Organov @ 2011-10-13 19:44 ` PJ Weisberg 4 siblings, 0 replies; 36+ messages in thread From: PJ Weisberg @ 2011-10-13 19:44 UTC (permalink / raw) To: git On Thu, Oct 13, 2011 at 8:53 AM, arQon <arqon@gmx.com> wrote: >>git co master > error: Your local changes to the following files would be overwritten by > checkout: > file1.txt > Please, commit your changes or stash them before you can switch branches. > Aborting > > I'm sure if I thought about it enough (ie re-read Andreas's post a couple > more times) I'd be able to understand why git gets it right sometimes but > not other times, but I'm too tired right now. Even when I *am* awake and Git gets it "right" (by your definition) when file1.txt on one branch is different from file1.txt on the other branch. That means that switching branches would require changing the file, so it refuses to overwrite your changes by doing so. If it CAN switch branches without losing your changes, it does. The fundamental problem is that you're thinking of the changes to the working tree (which aren't commited) as being "on" some branch. Until they're committed, changes in the working tree are only in the working tree. That's basically the difference between "committed" and "not committed". -PJ ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [BUG] git checkout <branch> allowed with uncommitted changes 2011-10-13 13:58 ` [BUG] " arQon 2011-10-13 14:46 ` Carlos Martín Nieto @ 2011-10-13 16:08 ` Holger Hellmuth 1 sibling, 0 replies; 36+ messages in thread From: Holger Hellmuth @ 2011-10-13 16:08 UTC (permalink / raw) To: arQon; +Cc: git On 13.10.2011 15:58, arQon wrote: > Andreas Ericsson<ae<at> op5.se> writes: >> there's no reason to refuse the branch change. >> Partly because nothing will be lost > > Actually, this isn't true either, because of the second bug: doing a revert > in branchA causes the changes in branchB to be lost. This can't possibly be > the intended behavior: again, it completely violates the integrity of branches > by allowing changes on one branch to impact a different branch. I assume you mean revert through 'git checkout' and not through 'git revert'. Git uses a different philosphy. It works best with small commits and commits done often. It assumes that when you switch branches, you don't switch your brain as well and still know for what purpose you changed tr_font.cpp (and even if you forget you always can check with git diff). It also reminds you that tr_font.cpp is changed when you switch branches (remember the "M tr_font.cpp" printed when you switched to another branch). It assumes that when you use 'git checkout --' to wipe out changed files without committing them anywhere(!) that you have thought about it the same way you have thought about before deleting or overwriting any file in the file system. The same way you have thought about before deleting or overwriting an uncommitted file in svn. What you term integrity of the branch is a model you made of the workings of svn that you now try to pin onto a different model. ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [BUG] git checkout <branch> allowed with uncommitted changes 2011-10-13 11:51 ` arQon 2011-10-13 12:22 ` Andreas Ericsson @ 2011-10-13 12:42 ` arQon 2011-10-13 12:55 ` Holger Hellmuth 2011-10-13 14:44 ` Victor Engmark 1 sibling, 2 replies; 36+ messages in thread From: arQon @ 2011-10-13 12:42 UTC (permalink / raw) To: git Simple testcase: >git init Initialized empty Git repository in C:/git-test/.git/ >notepad file1 >notepad file2 >git st # On branch master # Initial commit # Untracked files: # (use "git add <file>..." to include in what will be committed) # file1.txt # file2.txt nothing added to commit but untracked files present (use "git add" to track) >git add . >git st # On branch master # Initial commit # Changes to be committed: # new file: file1.txt # new file: file2.txt >git commit -am "init" 2 files changed, 2 insertions(+), 0 deletions(-) create mode 100644 file1.txt create mode 100644 file2.txt >git co -b foo Switched to a new branch 'foo' >notepad file1 (edit stuff) >git st # On branch foo # Changes not staged for commit: # modified: file1.txt >git co master M file1.txt file1 now has the wrong data in it for "master" branch. If I go back to "foo" branch and commit the file before doing anything else, it recovers, and changing branches works correctly again. -- "If you have local modifications to one or more files that are different between the current branch and the branch to which you are switching, the command refuses to switch branches in order to preserve your modifications in context." Maybe I'm just missing something obvious, but at the time that last "git co master" was issued: The file is locally modified. The file is different on the current branch (foo) than on the branch to which I am switching (master). The command fails to refuse to switch branches. So I guess the problem is that since the file wasn't re-added after the edit, git is ignoring it when trying to see if it's safe to branch or not? ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [BUG] git checkout <branch> allowed with uncommitted changes 2011-10-13 12:42 ` arQon @ 2011-10-13 12:55 ` Holger Hellmuth 2011-10-13 14:44 ` Victor Engmark 1 sibling, 0 replies; 36+ messages in thread From: Holger Hellmuth @ 2011-10-13 12:55 UTC (permalink / raw) To: arQon; +Cc: git On 13.10.2011 14:42, arQon wrote: >> git co -b foo > Switched to a new branch 'foo' >> notepad file1 > (edit stuff) >> git st > # On branch foo > # Changes not staged for commit: > # modified: file1.txt > >> git co master > M file1.txt > > Maybe I'm just missing something obvious, but at the time that last "git > co master" was issued: > > The file is locally modified. > The file is different on the current branch (foo) than on the branch to which > I am switching (master). Wrong. On branch foo as well as on master the same old file1.txt is committed. You never staged nor committed the new file1.txt anywhere. > The command fails to refuse to switch branches. ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [BUG] git checkout <branch> allowed with uncommitted changes 2011-10-13 12:42 ` arQon 2011-10-13 12:55 ` Holger Hellmuth @ 2011-10-13 14:44 ` Victor Engmark 2011-10-13 16:17 ` arQon 1 sibling, 1 reply; 36+ messages in thread From: Victor Engmark @ 2011-10-13 14:44 UTC (permalink / raw) To: arQon; +Cc: git On Thu, Oct 13, 2011 at 12:42:42PM +0000, arQon wrote: > Simple testcase: > > >git init > Initialized empty Git repository in C:/git-test/.git/ > >notepad file1 > >notepad file2 > >git st > # On branch master > # Initial commit > # Untracked files: > # (use "git add <file>..." to include in what will be committed) > # file1.txt > # file2.txt > nothing added to commit but untracked files present (use "git add" to track) > > >git add . > >git st > # On branch master > # Initial commit > # Changes to be committed: > # new file: file1.txt > # new file: file2.txt > > >git commit -am "init" > 2 files changed, 2 insertions(+), 0 deletions(-) > create mode 100644 file1.txt > create mode 100644 file2.txt > > >git co -b foo > Switched to a new branch 'foo' > >notepad file1 > (edit stuff) > >git st > # On branch foo > # Changes not staged for commit: > # modified: file1.txt > > >git co master > M file1.txt > > file1 now has the wrong data in it for "master" branch. The most important thing a VCS should do is to keep history intact. That happens when you check out in Git: No branches were changed, only the working space. The second most important thing a VCS should do is not destroy any of your uncommitted work unless you tell it to. That also happens when you check out in Git. The third most important thing a VCS should do is facilitate the developer's workflow. One common thing to do is to work on some thing, for example refactoring. During this process you might realize that one of the changes actually fixed a bug in the software. To keep things in their right place, you could now either 1. `checkout master` and commit the fix there, then shift back and continue working, or 2. commit the refactorings, `checkout master`, and commit the fix there. Either of these are easy to do with Git. There really is no reason why the changes in the workspace should be considered as "part of" the currently active branch, because they *are* not. Cheers, V -- terreActive AG Kasinostrasse 30 CH-5001 Aarau Tel: +41 62 834 00 55 Fax: +41 62 823 93 56 www.terreactive.ch Wir sichern Ihren Erfolg - seit 15 Jahren ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [BUG] git checkout <branch> allowed with uncommitted changes 2011-10-13 14:44 ` Victor Engmark @ 2011-10-13 16:17 ` arQon 2011-10-14 7:16 ` Victor Engmark 0 siblings, 1 reply; 36+ messages in thread From: arQon @ 2011-10-13 16:17 UTC (permalink / raw) To: git Victor Engmark <victor.engmark <at> terreactive.ch> writes: > 1. `checkout master` and commit the fix there, then shift back and > continue working I absolutely agree. And it's far more common than any of us would like. My point is, you *can't* do this in git without first staging your current branch via either commit or stash, or you risk changes bleeding between the branches and/or work being lost irretrievably. This is not something that you would expect, and as you say: > The second most important thing a VCS should do is not destroy any of your uncommitted work unless you tell it to ... which is exactly what git does, and why I have a problem with it. But the response here is uniformly "that's just how git is", so obviously it's something you learn to become aware of over time, and avoid. It's not going to get "fixed", because people who are used to git don't see it as a bug, so I just have to decide whether I can live with it or not. ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [BUG] git checkout <branch> allowed with uncommitted changes 2011-10-13 16:17 ` arQon @ 2011-10-14 7:16 ` Victor Engmark 0 siblings, 0 replies; 36+ messages in thread From: Victor Engmark @ 2011-10-14 7:16 UTC (permalink / raw) To: arQon; +Cc: git On Thu, Oct 13, 2011 at 04:17:51PM +0000, arQon wrote: > Victor Engmark <victor.engmark <at> terreactive.ch> writes: > > 1. `checkout master` and commit the fix there, then shift back and > > continue working > > I absolutely agree. And it's far more common than any of us would like. > My point is, you *can't* do this in git without first staging your current branch > via either commit or stash, or you risk changes bleeding between the branches > and/or work being lost irretrievably. It's been pointed out enough times already that work is *not* lost (at least unless you --force it to) *nor* the branches corrupted, so I'll just advice to look at more Git documentation. I used CVS 2004-2006 or so, Subversion 2006-2009, and Git since then. It's vastly superior to either, and it's really difficult to lose any work unless getting into the habit of forcing every change. > This is not something that you would > expect, and as you say: > > > The second most important thing a VCS should do is not destroy any of your > uncommitted work unless you tell it to > > ... which is exactly what git does, and why I have a problem with it. No, it does not. Others have explained this better already. > But the response here is uniformly "that's just how git is", so obviously it's > something you learn to become aware of over time, and avoid. It's not going to > get "fixed", because people who are used to git don't see it as a bug, so I just > have to decide whether I can live with it or not. It took a while to get my head around just how broken the Subversion model was, and why my expectations from using that model kept resulting in "weird" state (although don't get me started on `svn clean`). Don't worry, you'll see the light :) -- terreActive AG Kasinostrasse 30 CH-5001 Aarau Tel: +41 62 834 00 55 Fax: +41 62 823 93 56 www.terreactive.ch Wir sichern Ihren Erfolg - seit 15 Jahren ^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [BUG] git checkout <branch> allowed with uncommitted changes 2011-10-13 8:40 [BUG] git checkout <branch> allowed with uncommitted changes arQon 2011-10-13 10:48 ` Nguyen Thai Ngoc Duy @ 2011-10-13 15:09 ` Michael J Gruber 1 sibling, 0 replies; 36+ messages in thread From: Michael J Gruber @ 2011-10-13 15:09 UTC (permalink / raw) To: arQon; +Cc: git arQon venit, vidit, dixit 13.10.2011 10:40: > Which, as you'd expect, results in both the on-disk copies and other branches > becoming corrupted. > > Tested on git versions 1.7.6 and 1.7.7 (msysgit) > > http://benno.id.au/blog/2011/10/01/git-recursive-merge-broken describes > something that sounds similar, but that's supposedly fixed on 1.7.7, > whereas this happens on that as well. > > master is a tracking branch, "ttfcon" is the branch I was using to develop > a change. Got to a good point on the branch, merged it in: > > $ git co master > $ git merge ttfcon > Updating b9f0c75..6280b7a > Fast-forward > .gitignore | 2 ++ > code/renderer/tr_font.cpp | 27 ++++++++------------------- > 2 files changed, 10 insertions(+), 19 deletions(-) > > $ git st > # On branch master > # Your branch is ahead of 'origin/master' by 3 commits. > > back to the branch to mess around with a couple of things to be sure this > is what i want to push > $ git co ttfcon > do stuff > > $ git st > # On branch ttfcon > # 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: code/freetype-2.3.11/builds/win32/visualc/freetype.vcproj > # modified: code/renderer/tr_font.cpp > > so far so good... > > $ git ci -m "blah" code/freetype-2.3.11/builds/win32/visualc/freetype.vcproj > 1 files changed, 4 insertions(+), 0 deletions(-) > > note that tr_font is locally modified and still *not committed* at this point. and neither staged for commit, exactly. > $ git co master > M code/renderer/tr_font.cpp > Switched to branch 'master' > Your branch is ahead of 'origin/master' by 3 commits. > > boom. instead of rejecting the branch change, git switches branches anyway, > and doesn't do anything about the uncommitted changes in the file itself - Exactly. git leaves them as they are, without changing what you have in your work tree. (This is possible because the switch ttfcon to master involves no changes which conflict with the chnage that you have in your work tree). > meaning they're now effectively "in" master because they're still on disk, > so now the master is poisoned. Not at all. They are on "disk" (work tree). Full stop. Not staged, not committed, not at all "in master". > > "git st" does show the change: > > # On branch master > # Changes not staged for commit: > # modified: code/renderer/tr_font.cpp > > but it's a change I never MADE on this branch (ie master), only on the > other branch. You never made it on the other branch either. You made it in the work tree. And "git status" clearly says so: modified, not staged. > "git diff" is just as confused as I am: > > $ git diff ttfcon > --- a/code/renderer/tr_font.cpp > +++ b/code/renderer/tr_font.cpp > + // git branch bug "git diff" shows you the change you have in your work tree, i.e. the difference between index (which coincides with master since nothing is staged) and work tree. The fact that there is a difference is equivalent to saying "there are unstaged changes". > So it's picking up the difference between the two branches, but as far as No. The difference between the branches is the change to freetype.vcproj because you committed that to ttfcon, not master. > the *actual file* goes, master now has a line in it that shouldn't be there. It's in the work tree, not master.... > I'm just trying out git as a possible replacement for SVN, so maybe I'm > mistaken about what "should" happen, but AIUI git switching branches with > uncommitted changes is a bug (and given that it poisoned a branch that I > wasn't on, it certainly looks like one). A couple of days ago it DID complain > when I tried to switch with uncommitted files still present, so it was working > properly then. I have no idea what's made it happy to ignore them now: > nothing's changed that I know of. When switching branches, git tries to preserves the changes that you have in your work tree. If it is possible (because there is no overlap, as written above), it hapilly does just that. If not it barks. I think you have to wrap your head around the Git model after unwinding it from the svn model, which is normal ;) Cheers, Michael ^ permalink raw reply [flat|nested] 36+ messages in thread
end of thread, other threads:[~2011-10-16 22:05 UTC | newest] Thread overview: 36+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2011-10-13 8:40 [BUG] git checkout <branch> allowed with uncommitted changes arQon 2011-10-13 10:48 ` Nguyen Thai Ngoc Duy 2011-10-13 10:59 ` Alexey Shumkin 2011-10-13 11:51 ` arQon 2011-10-13 12:22 ` Andreas Ericsson 2011-10-13 13:09 ` arQon 2011-10-13 13:59 ` Carlos Martín Nieto 2011-10-13 17:09 ` [CLOSED] " arQon 2011-10-13 18:56 ` Alexey Shumkin 2011-10-13 19:01 ` Jakub Narebski 2011-10-13 13:58 ` [BUG] " arQon 2011-10-13 14:46 ` Carlos Martín Nieto 2011-10-13 15:53 ` arQon 2011-10-13 16:17 ` Alexey Shumkin 2011-10-14 6:51 ` Alexey Shumkin 2011-10-13 16:32 ` Holger Hellmuth 2011-10-13 17:04 ` Carlos Martín Nieto 2011-10-13 18:19 ` arQon 2011-10-13 18:28 ` Junio C Hamano 2011-10-13 18:56 ` arQon 2011-10-14 1:38 ` Jeff King 2011-10-14 9:27 ` Holger Hellmuth 2011-10-14 9:54 ` Victor Engmark 2011-10-16 18:25 ` arQon 2011-10-16 20:37 ` Junio C Hamano 2011-10-16 22:04 ` Holger Hellmuth 2011-10-13 20:07 ` Carlos Martín Nieto 2011-10-13 17:06 ` Sergei Organov 2011-10-13 19:44 ` PJ Weisberg 2011-10-13 16:08 ` Holger Hellmuth 2011-10-13 12:42 ` arQon 2011-10-13 12:55 ` Holger Hellmuth 2011-10-13 14:44 ` Victor Engmark 2011-10-13 16:17 ` arQon 2011-10-14 7:16 ` Victor Engmark 2011-10-13 15:09 ` Michael J Gruber
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).