I often find myself in branch A, with everything checked in and compiled, wanting to look at something on branch B. I hop to branch B, look, and come back to branch A. Unfortunately, when I then do a make, files that differed between A and B will be recompiled, as well as any further dependencies. I wonder if it would be possible or desirable to have a config flag that told git to restore the timestamps across branch checkouts in order to prevent this perturbation. So, when git does a checkout of a branch, it would look to see which files in the current branch are changed, tuck away the timestamps for those, and switch to the new branch. On return to the former, the same would be done for the new branch, then after the changed files were restored, the timestamps would be reset. One thing this would enable is to be able to hold the compilation products of multiple branches at the same time in the same working tree, switch back and forth between branches, and only have to compile code that you actually modify. Currently, we store compilation products in a directory that is composed of the architecture, compiler, compiler options, and so forth, among which also could be the branch name. Anyway, just an idea I thought worth batting about. Bill -
Almost every SCM has such a flag. And every one of them warn For instance, timestamp of which machine do you want to restore? Consider separating build and working repositories. Merge things into build repo, switch the branches freely in your working repo. Works just fine for me. -
Hi Bill, I did that, too, until git-show learnt about the nice ":" syntax. For example, if I want to know what is in branch B, I do $ git show B: which shows the root directory of the revision "B" (this is in line with <commit>:<pathspec> if you interpret "" as the root path). The subtrees are all identified by trailing slashes. Then you can say $ git show B:Documentation/Makefile If you want to know the differences to the file "doc/GNUMakefile" in your current working tree, do $ git diff B:Documentation/Makefile -- doc/GNUMakefile No need to switch branches. And if you _do_ need to switch branches, why not make a local clone, sharing the object database: $ git clone -l -s . test-directory This is _very_ fast, since it basically checks out the branches in test-directory/. Right now, you have to go to the test-directory, and switch the branches manually (I think), but talk has been that you may be able to tell git-clone which branch you really want. Hth, Dscho -
I think you're much better off just using multiple repositories instead, if this is something common. Messing with timestamps is not going to work in general. It's just going to guarantee you that "make" gets confused in a really bad way, and does not recompile *enough* instead of recompiling *too much*. Git does make it possible to do your "check the other branch out" thing very easily, in many different ways. You could create some trivial script that does any of the following (ranging from the trivial to the more exotic): - just create a new repo: git clone old new cd new git checkout origin/<branch> and there you are. The old timestamps are fine in your old repo, and you can work (and compile) in the new one, without affectign the old one at all. Use the flags "-n -l -s" to "git clone" to basically make this instantaneous. For lots of files (eg big repos like the kernel), it's not going to be as fast as just switching branches, but havign a second copy of the working tree can be quite powerful. - do the same thing with just a tar-ball instead, if you want to git archive --format=tar --prefix=new-tree/ <branchname> | (cd .. ; tar xvf -) which is really quite fast, if you just want a snapshot. - get used to "git show", and just look at individual files. This is actually *really* useful at times. You just do git show otherbranch:filename in one xterm window, and look at the same file in your current branch in another window. In particular, this should be trivial to do with scriptable editors (ie GNU emacs), where it should be possible to basically have a whole "dired mode" for other branches within the editor, using this. For all I know, the emacs git mode already offers something like this (I'm not an emacs user) - and in the extreme example of that "virtual directory" thing, there was at least somebody working on a git plugin for FUSE, ie you could literally ...
Hi, You mean http://www.sfgoth.com/~mitch/linux/gitfs/? Funny, it came up on IRC a few days ago. gitster said he'd issue "mkdir" instead of "git checkout -b" by mistake somtimes... Ciao, Dscho -
Like others have already recommended, I usually just use separate repositories to work around this problem. Of course, the proper fix is to use a make-like tool that uses content hashes as well as timestamps to decide if a file has been updated ... -- Karl Hasselstr
* Bill Lear <rael@zopyra.com> [070302 08:28]: > On Friday, March 2, 2007 at 10:14:26 (+0100) Karl Hasselstr
Hi, On Fri, 2 Mar 2007, Bill Lear wrote: > On Friday, March 2, 2007 at 10:14:26 (+0100) Karl Hasselstr
Hi, On Fri, 2 Mar 2007, Karl Hasselstr
Hi, On Mon, 5 Mar 2007, Karl Hasselstr
>On Mon, 5 Mar 2007, Karl Hasselstr
Hi, > >On Mon, 5 Mar 2007, Karl Hasselstr
>> >On Mon, 5 Mar 2007, Karl Hasselstr
Hi, Think about it. Why would the timestamp change? Because Git wrote the file? But that was exactly the behaviour you were complaining about. Ciao, Dscho -
Not because git wrote the file, but because git notices that content changes, and writes the file (and timestamps it) "smartly". If someone writes into the repo, the timestamp stored becomes invalidated and the write of the file just creates the timestamp at the time of the checkout. If no write into the repo index occurs, the stored timestamp is applied after the file is checked out. Bill -
But Bill, don't you realize that restoring the timestamp is *WRONG*? There's no way that git can know whether you did a "make" in between switching back and forth between branches. That's true on a very fundamental level, but it's doubly true when anybody uses a separate object directory (which doesn't leave any information *at*all* in the source tree about the fact that somebody did a "make"). So stop even asking for this. We'd have to be totally and utterly incompetent to do what you ask for. We're simply not that stupid. We already pointed out how you can do what you want to do *other* ways that are *not* idiotic and incompetent. I don't think you even answered. Linus -
Maybe, maybe not. Each argument I've seen doesn't convince me. Sure, it may be MESSY. It may be UGLY, and therefore undesirable, but I don't think any of the arguments have conclusively shown that it Why should I care whether git knows this? I never said it should. As I said, if I have make products in separate, per-branch directories (a minor extension to my current make system), I don't see how this would be confusing in the least. Git should only care if the content of the file in the index changes. It shouldn't care in the least about my Here's the flow. Perhaps I'm fundamentally confused, and I'll be the first to admit that is true in plenty of ways: I edit sourcefile.c, compile it, then commit it with N=timestamp(sourcefile.c) on master. N is < timestamp(.master/sourcefile.o). I then switch to branchX. N is stored by git for master:sourcefile.c. No stored timestamp are on this branch, so the file gets the timestamp it gets on checkout M=timestamp(sourcefile.c). I compile the file again, all is well. I move back to master branch. Git stores M as branchX:sourcefile.c Git checks out the file, and stamps it with N. I do a make. No recompilation happens. I switch back to branchX, the file is checked out and stamped with timestamp M. I do a make. No recompilation happens. Happy happy, joy joy. If someone pushes into my repo, as Johannes suggested (how that would work, being a non-bare repo, is beyond me, but whatever), the timestamp for that file on that branch would be invalidated, and the file would get whatever timestamp it got when it was written to disk. Now, all of this may be DISTASTEFUL, UGLY, POOR DESIGN, etc., but I don't see how it is WRONG. As someone who has professed the motto "actually useful is a lot better than clean, but not as useful", I am not asking for this, I'm just arguing the point, waiting for a convincing argument rather than having someone call me "idiotic and incompetent" and "stupid" for asking for it in the first ...
I'm sorry. If you don't see how it's WRONG to seta datestamp back to something that will make a simple "make" *miscompile* your source tree, I don't know what defintiion of "wrong" you are talking about. It's WRONG. It's STUPID. But Bill, the content in the index *does* change. It's that simple. It changes every time you check out another branch. And if it doesn't change, git already avoids changing mtime (because git already avoids changing the WHICH IS WRONG! You need to recompile, since the compile you did on the other branch DOES NOT MATCH in "sourcefile.c" any more. And if sourcefile.c _does_ match in the two branches, then git *already* won't have changed it at all, so git already does the obvious optimization. The thing is, "ccache" actually does this right. You could arguably integrate ccache with more git integration, and let ccache just use the SHA1's that git already caches and knows about. But the real issue is that what _you_ suggest is crazy. It doesn't work. Linus -
Well, I'll let it drop after this, but I think you're wrong. I do NOT need it to recompile when I do the third make above. The time stamps match up perfectly with the make products, the make system is NOT confused, the appropriate rebuilds occurs WHEN I want them to, and my make products are thereafter a model of wholesome sanity and blissful unity. Again, this may be violating a sacred rule of "thou shalt not f~ck with timestamps", but I'm not religious on that point. I share the desire of never getting make products when I should not, and appreciate the desire to never, ever, NOT recompile something when it must, which is what the above example does. I also understand there are better ways than having git do this with timestamps, it's just that I'm not understanding your logical argument, even with all caps emphasizing your points. Perhaps I'll build a prototype, have it I'll let this drop. It appears we are not communicating, which you seem to be translating and signaling (in all caps, no less) as "you are stupid". That's ok, I've felt that way about others from time to time, so I understand and sympathize with your frustration. I do thank you (all) for pointing out the much less invasive alternatives, using git (right now) and still, despite this rather heated exchange, think git is a very cool and thoughtfully put together collection of software. Bill -
Hi,
Bill, maybe you don't want to hear it, but for all those following this
thread, here is why you are wrong:
"make" does _not_ match the time stamps of xyz.c and xyz.o. After you
"make", the only thing which is guaranteed is that if xyz.c is _newer_
than xyz.o, the compiler is started.
Example:
00:05 you pull upstream into your master branch, which has a newer xzy.c
00:07 you type make. xyz.o is built, because make sees that xyz.c is
newer than xyz.o
00:12 you checkout your side branch, xyz.c is updated.
00:13 you type make, and again xzy.o is built, because xyz.c is newer than
xyz.o
00:25 you switch back to your master branch.
Now, if your wish would be granted, and xyz.c has the same timestamp as
before, then it _still_ is older than xyz.o. So make will not rebuild it.
BUT xyz.o is actually compiled from the side branch's version of xyz.c!
Hth,
Dscho
-
An actual demonstration of my stupidity is much, much preferable
No, I think you missed my point. There are two xyz.o's:
One in .master/xyz.o, and one in .branchX/xyz.o. So, you're example
becomes:
00:05 you pull upstream into your master branch, which has a newer xzy.c
00:07 you type make. .master/xyz.o is built, because make sees that xyz.c is
newer than .master/xyz.o
00:12 you checkout your side branch, xyz.c is updated.
00:13 you type make, and .branchX/xzy.o is built, because xyz.c is newer than
.branchX/xyz.o
00:25 you switch back to your master branch.
00:26 you type make, and nothing happens, as it should not. You are
happy, and thank the git community for all of their heroic efforts.
Now, I'm really going to go: the family is hungry and I've got
dinner to prepare, so if you want to flame me for opening my mouth
further, feel free.
Bill
-
Hi, Why not put the two xyz.c's into .master/ and .branchX/ as well (surely, the source files are small compared to the object files)? And just to make sure, the Makefile, too (some Makefile targets depend on the timestamp of this, too). And to make sure that if we're switching to a third branch, let's put the files there, even when the side branch does not change them, otherwise A->B->C->A might fail. And while at it, we could put the information about which branch this is into the corresponding directories, too! Otherwise, we could rename the directory by mistake, and the system would stop working. And the corresponding refs. They could be there, too. Hth, Dscho P.S.: Google for the complicator's gloves. -
This all sounds a lot like git-clone's "alternate" code. Does a repository cloned with the -s or --references flag have some setting to make fetch and push work with the same remote repositories as the local origin, or do the remotes have to be manually propagated between the two local copies? If I git-fetch in the local clone, does it write the new objects to the local origin? My own work habits are very similar to Bill Lear's, but my projects' build times are small enough that it's less pain to rebuild half the project than to propagate changes recorded under $GIT_DIR between local branches. I have not found a git workflow that makes me entirely happy, but I suspect I just don't know the magic words. Michael Poole -
Hi, So, what do you want to do? Ciao, Dscho -
I want to have several local directories -- including build products and configuration files that are neither build products nor revision controlled -- that correspond to certain branches of one project. (Sometimes I have several trees for a single branch, to handle compile-time alternatives.) I do not much care whether there is a separate source tree for each of these or not. When I switch from working on one branch to another, I do not want file timestamps to be any later than the corresponding object was changed in the repository. When I change configuration options (including which branch(es) go to which remote(s)), I want to make that change in one $GIT_DIR rather than in one $GIT_DIR for each branch. As a lower priority, I would like a fetch on any of the branches to have results that are visible to all my local copies without more network traffic. The first two goals are neatly solved by having several local clones. The third and fourth are where I get lost. Michael Poole -
Hi, This can be solved by symlinking the config to one designated repo (let's I'd just make a small script which I'd run from the "master" repo instead of saying "git pull": -- snip -- git pull || exit for branch in branch1 branch2 branch3; do cd $branch && git pull .. $branch && cd .. || exit done -- snap -- This assumes that you have named the side branches "branch1", "branch2" and "branch3", and that they are checked out in the subdirectories of the same name. Hth, Dscho -
These days I use a few working trees that are connected to my primary repository (which also has a working tree). The primary total 120 drwxrwsr-x 3 junio src 4096 Mar 5 16:22 ./ drwxrwsr-x 15 junio src 16384 Mar 5 16:23 ../ -rw-rw-r-- 1 junio src 41 Mar 5 16:22 HEAD lrwxrwxrwx 1 junio src 27 Mar 3 22:53 config -> /src/git/.git/config lrwxrwxrwx 1 junio src 26 Mar 3 22:53 hooks -> /src/git/.git/hooks/ -rw-rw-r-- 1 junio src 82455 Mar 5 16:22 index lrwxrwxrwx 1 junio src 25 Mar 3 22:53 info -> /src/git/.git/info/ drwxrwsr-x 3 junio src 4096 Mar 3 22:59 logs/ lrwxrwxrwx 1 junio src 28 Mar 3 22:53 objects -> /src/git/.git/objects/ lrwxrwxrwx 1 junio src 32 Mar 3 22:53 packed-refs -> /src/git/.git/packed-refs lrwxrwxrwx 1 junio src 25 Mar 3 22:53 refs -> /src/git/.git/refs/ lrwxrwxrwx 1 junio src 28 Mar 3 22:53 remotes -> /src/git/.git/remotes/ lrwxrwxrwx 1 junio src 29 Mar 3 22:53 rr-cache -> /src/git/.git/rr-cache/ It shares everything other than HEAD and the index (the reflog for branches are also shared by a symlink .git/logs/refs pointing at the one in the primary repository). This risks confusion for an uninitiated if you update a ref that is checked out in another working tree, but modulo that caveat it works reasonably well. We might want to add an option to 'git-clone' to create something like this, but I am somewhat worried about the newbie confusion factor. Perhaps... $ git clone --i-know-what-i-am-doing-give-me-an-alternate-working-tree \ /src/git /src/git.wk0 -
Hi, If you would have cared to actually read and try to understand my reply here: http://article.gmane.org/gmane.comp.version-control.git/41136 (This was 5 days and a very long thread ago) you would have seen long ago that I actually see your problem, and want the something similar myself. This is what I "concede". Always have. Only that I use a sane method to achieve it. And that was my point you consistently refused to accept. You don't have to thank me, as you clearly chose to ignore my help. Ciao, Dscho -
Which I did, your baseless presumption to the contrary Your presumption is again false: your point was that my logic was confused, that the entire dependency scheme I sketched out was "stupid", and you and another expended considerable effort to show how stupid this was, which now is clearly wrong --- my explanation and example wasn't stupid after all. I was merely trying to convey WHAT I wanted to have happen, and HOW, logically speaking, it could. What I got from you and one other ON THIS PART was that my logic was STUPID, IDIOTIC, etc., though to their credit, several others merely chimed in with their opinion and helped the discussion along by presenting argument, example, and not invective and mere assertion that my logic was very much beneath contempt. I saw and appreciated your earlier explanation, and will be trying to work with it, and those the others suggested. My guess is that it will not be as buttery-smooth as I would have hoped, but it will probably do well enough. Your petulance and quick temper to dismiss someone as stupid merely because he pursues a line of discussion that you yourself admittedly confuse, not to mention your name-calling --- both explicit and veiled --- really is not helpful, though your suggestions on how to use git better certainly are, and I do very much appreciate them here, and elsewhere. Bill -
For most users, there are no dedicated branch-specific build directories. In any situation where there _are_ such branch/arch/config-option specific builddirs, someone has crafted a neat multi-<factor> build system. Now, if you have such a build system, it's trivial to have a separate checkout for each branch. Trying to push this bit of complexity into git means that git would have an option that lets most users shoot themselves in the foot, big time. So - your ideas are OK, but just do all the trickery and magic for the super-build-system _in_ the super-build-system. You don't need any GIT changes, just take advantage of the really fast and lightweight "local clone". I guess that's the definition of "WRONG" above. It's wrong and error-prone for most users, and for the handsome few that could take advantage of it, there are better ways of doing it. cheers, martin -
Are you assuming that the makefile will automatically figure out which branch you are on, and then redirect the .o to the right <.branch-name> directory? That's the only thing that makes sense, since if you are using VPATH and depending on the developer being cd'ed into .master when the current branch is master, and cd'ed into .branchX when the current branch is branchX, and the developer types make at when they are in the .master directory but the current branch is branchX, the result will be a huge, confusing mess. But of course, the Makefile is under source control itself, and if at a previous point in time the Makefile didn't have the magic .git directives, then you could do the build and have the the wrong thing happen. So it seems to be a very fragile solution compared to using multiple working directories, or using ccache. It could be a tad bit more efficient than using ccache or multiple directories, but the real question is whether it really is worth the effort, and potential support difficulties if some confused user turns on this feature with the proper git magic in their makefiles, and then the git mailing list gets the support burden. That being said, I have often wished that there was some way I could use all of those autogenerated html and man pages to spead up the "make doc" process in git. Ccache doesn't work because it doesn't understand asciidoc or xmlto, and there are all of these conveniently generated output files in the origin/man and origin/html, but unless we are building exactly the same git release as described in the log message in the origin/man or origin/html branch. What would be really cool would be some way of generating some kind of database that mapped the SHA1 hash of the SHA1 hash of the dependencies of a particular output file to the SHA1 hash of the glob of the generated output file as found in origin/man and origin/html. This would basically be a way of integrating ccache functionality into git, but for the HTML and man ...
Are you not describing a situation where git would modify a file ("move back to branchX"), and no recompilation happens (whereas it should)? -- Matthieu -
Hi, It may not be infeasible. But it is wrong. It "fixes" a totallc clear idiom, namely that every time a file is written into, the timestamp changes. And guess what, "touch <file>" is the best proof that sometimes, you want that this happens, even Of course this works. That is a fundamental feature of Git: if you strip a This approach is so fragile! It is invasive, easy to get wrong (count the ways how to invalidate the timestamp), and serves only an obscure use FWIW I have to agree here. I saw quite a few projects go wrong, because management insisted on abolishing a perfectly good design, just because No. This is not what Linus was referring to (unless I am really wrong here, which I refuse to believe). We pointed out, in several ways, how much easier it is to create a throw-away working directory. It is easy, robust, and can be done _right now_ with Git. Ciao, Dscho -
This is not my "pet idea". I could care less about it: I have other alternatives. I was just engaging in what I hoped would be a friendly exchange about this, but it seems to have touched a nerve, and then invective with unsubtle charges of STUPID was loaded into the catapult and flung across the sea ... I loathe politics getting in the way of something clean, robust, and useful. I would be the last to advocate it: besides were I really convinced that git MUST have this or die, I would try to write it myself --- I was just hoping for an argument showing why it was such a lame-brained idea from a logical, not implementation, standpoint. Thanks again for your time. Bill -
Hi, You know why you put that in quotes? I know. Because it is not smart to do that. Ciao, Dscho -
The tone on this list is usually pretty civil, and I have benefited a lot from the discussions here, and greatly appreciate the effort put in by all concerned, but this sort of tone --- implying that I am stupid to even query about this --- is really not very helpful, and quite rude and childish. Bill -
On Friday 2007 March 02 16:21, Karl Hasselstr
On 2007-03-05 12:13:50 +0000, Andy Parkins wrote: > On Friday 2007 March 02 16:21, Karl Hasselstr
On Monday 2007 March 05 12:33, Karl Hasselstr
On 2007-03-05 13:19:15 +0000, Andy Parkins wrote: > On Monday 2007 March 05 12:33, Karl Hasselstr
All very wrong if you ignore what I wrote as part of my original note: keep compilation products separated by branch name, not in the same place. This is essential to my request: without it, it is indeed very wrong. We currently separate out by compiler, options, machine architecture, and adding the branch to that is trivial. Bill -
I realise why it's causing you troubles. However, I was hoping that that little example shows why it can never be right to use the timestamp out of I'm afraid that the unnecessary recompile is just a by-product of that organisation. I still say that git is correct to touch the file dates. [blatent plug]: perhaps my poorman's submodule support will get you by until real submodule support is implemented? http://lists.zerezo.com/git/msg334639.html I doubt it though - as you would probably want automatic checkout in your situation. Andy -- Dr Andy Parkins, M Eng (hons), MIET andyparkins@gmail.com -
I don't understand then. If the timestamp is stored per-branch, as it must be, then no effective change takes place whatsoever, and all products are compiled properly, and in their proper place. If master:source.c compiles to .master/source.o and has a timestamp .master/source.c.timestamp, switching to branch1 and back, and restoring the timestamp does not do anything wrong. It just prevents Well, git is certainly correct for those who want the standard behavior. I don't think the current submodule support will help, but I am keen to see submodules for other reasons. Bill -
