From: Bill Lear <hidden> Date: 2016-06-15 22:42:53
A perfect example of the sort of trouble I'm having with git just
happened again.
I have a public bare repo on my machine that I have cloned to make a
private repo. I just want to sync my branches on my public and
private repos. I do not want to merge across branches, I just want to
"sync".
So, here's what I did.
In my private repo:
% cat .git/remotes/origin
URL: /repos/git/project
Pull: refs/heads/master:refs/heads/origin
Pull: refs/heads/topic:refs/heads/topic
And this is the sequence of unfortunate events:
Starting on topic branch:
% git commit -a -m "Fix spacing rules"
% git checkout master
% git pull
[Won't pull non-fast-forward on my topic, so I try to get that synced.]
% git checkout topic
% git push
[ok, fine, seems good.]
[Now, instead of remembering to move back to master, I do this:]
% git pull
Trying really trivial in-index merge...
fatal: Merge requires file-level merging
Nope.
[AAAAGH!]
Merging HEAD with 37e229835103a11365b1e081f9b9987a88437e62
Merging:
e298e7f Skip rails in user nets
37e2298 Typofixen.
[NO NO NO! This is not what I want!]
found 1 common ancestor(s):
a2ba736 Try #2: Fixed (mostly harmless) bugs in handling of time variable.
Auto-merging src/ast/tstD.cc
Auto-merging src/meth/XMLImporter.cc
Auto-merging src/meth/XMLImporter.hh
Auto-merging src/meth/tstXMLI.cc
merge: warning: conflicts during merge
CONFLICT (content): Merge conflict in src/meth/tstXMLF.cc
Auto-merging src/nat/MacroFanLoader.cc
Auto-merging src/nat/VPE.cc
Auto-merging src/nat/PnDef.cc
Auto-merging src/nat/VLExporter.hh
Auto-merging src/nat/tstMod.cc
Automatic merge failed; fix conflicts and then commit the result.
Ok, now I'm hosed. Putting aside WHY git would do this to me (yes, I
know the answer is that I asked for it), on my topic branch I now have
tons of files listed when I do git status. git diff shows tons of
stuff I don't want in my branch.
So, I edit the file and "fix" the merge conflict, then realize that
this is probably not what I want to do at all.
So, 1) how do I get back to the status quo ante? I have about 30 files
listed as "Updated but not checked in", then this:
# Changed but not updated:
# (use git-update-index to mark for commit)
#
# unmerged: src/methodic/tstXMLI.cc
# modified: src/methodic/tstXMLI.cc
which I don't want, as I just want them to go away...
2) Why does git pull do the right thing when on master, but seemingly
changes behavior when on topic? I mean, the origin file seems to say
update topic from topic. It says nothing about updating topic from
master, which is what seems to have happened. When on master I get my
desired "sync" behavior, but when on topic, it merges cross-branch...
Bill
I have a public bare repo on my machine that I have cloned to make a
private repo. I just want to sync my branches on my public and
private repos. I do not want to merge across branches, I just want to
"sync".
Ok, others already replied, but here's a few rules to ease your mind in
general:
- First off: you can always _trivially_ get back to whatever state you
had before, as long as you committed it, and didn't have any dirty
state (uncommitted patches) in your working tree.
This is something that it's worth repeating, and even perhaps
experimenting with to get really comfortable with. Why? Because once you
learn to get back to any random state you had before, and once you are
comfortable with that, you suddenly lose the fear of experimenting.
Whatever you screw up, if you're confident you can get back, who cares?
So the "get back from a mistake" should probably be at the very front of
our manuals and tutorials. I don't think it currently is, but it's
actually not that hard. There's just one command to remember: "git reset",
and the only issue you might ever have with it is:
- make sure you're on the right branch first! If the problem you had is
that you're on the wrong branch, switch branches first! Don't try to
make the wrong branch "look right". But once you know you're on the
right branch, you know that "git reset" is your friend to getting it
anywhere you want.
- do you want to throw away all your working tree changes (and if
you screwed up some git operation, the answer is usually "Yes!"). If
so, add the "--hard" flag. It's not on by default, exactly because it
*will* throw away all state in your tracked working tree, and reset it
to whatever you want to go back to.
- exactly *what* do you want to go back to? The default is to go back to
the state at the last successful commit, but sometimes what you screwed
up was exactly the last commit (eg an unintentional "pull" that
actually succeeded), and then you need to tell it *what* to reset to.
That's really all there is to it. It's really simple, although especially
the second point can take some practice to get right.
So NORMALLY, if you did something bad - say, you edited a file, and just
realized that the whole edit was just crap, and you want to start over -
you just do a simple
git reset --hard
and it will just reset all your git state to the last commit you did.
This is what you'd do in this case, when you had a "git pull" that simply
*failed* due to conflicts, and you realize that you didn't do that merge
at all.
However, what happens if you actually do a "git pull" that doesn't have
any conflicts (or at least they merge fine), so the pull actually
*succeeds*, but you realize that wasn't what you wanted to do at all?
In that case, you need to say
git reset --hard <point-you-want-to-go-back-to>
to just reset to the previous state. Now we get to that "how do I figure
out what state that was?" part of the question, and usually it's trivial
to answer.
For example, a command like "git pull" will leave a special magic name
around to tell you what the original HEAD was before the pull, and that
magic name is (surprise surprise) called ORIG_HEAD. So if the pull
succeeded, but you realized it was an error (perhaps you had even intended
to do it, but once you pulled, you just saw that what you pulled was crap,
so you decide that you didn't really want to do it after all), you can
just do
git reset --hard ORIG_HEAD
and you're back to where you were _before_ the pull.
It really is that easy. And once you get comfortable with it, and you
really know deep down how easy it is, that should just relax you a lot.
When you go "AIEE! I made a horrible mistake!" you should just laugh, and
say "and I don't *care*, because I can just trivially undo it!".
Now, usually it's really as simple as just using ORIG_HEAD (or the
top-of-the-branch itself when the pull simply failed), but you can
actually do it for any commit. Say, you've worked for a week, and have
committed five or six things (and you don't even quite remember), and you
are just weary, and realize that IT IS ALL CRAP!
Now, before you just decide to drown your sorrows in a bottle (or,
perhaps, the morning after), you realize that you haven't actually pushed
it out to anybody else yet (because it wasn't ready anyway), and that you
can just undo the whole thing!
So what do you do?
You just fire up gitk, or whatever your favourite history viewer is (git
log, qgit, whatever), and you select the last good commit by hand, and do
git reset --hard <selected-commit-sha1-name>
which you just cut-and-paste from your history viewer. And magic happens.
It's all gone, and you're now at that old state in history, and all your
crap is gone, gone, gone. You can now have a drink or five, happy in the
knowledge that you just wasted five days of your life, but nobody will
ever even know your dark dirty little secret, and hopefully you're getting
paid by the hour, not by the end result anyway.
Of course, if you have reflogs enabled (see previous discussions), it's
even easier. In particular, it's easier if you do a "git reset" to some
other point in history, and suddenly realize that what you want to undo is
really that "git reset" itself ;)
(Even if you undo things, that's also recoverable, as long as you haven't
done any garbage collection. But it can be harder, because now you won't
get "git log" or "gitk" to show the stuff you undid, so this is where
reflogs can save your bacon, since they will remember the old stuff too.
Without reflogs, you either need to have it in ORIG_HEAD, or you need to
run "git fsck-objects" and look at all the dangling commits by hand).
So be happy. "git reset" can be dangerous (you *are* throwing things
away), but it's also very powerful, and pretty easy to use. And git makes
it fairly hard to *really* throw anything committed away, so even if you
undo something, and realize you want to re-do it again, it's possible to
go back - at most it's just a bit more involved to *find* the place to go
back to.
One final (and unrelated) note. If all you want to do is "sync up", and
not actually merge anything new into your current branch, you should just
do "git fetch". Not "git pull". Doing a "pull" implies merging into your
current branch, and thus does more than just "sync up" the branches you
are tracking.
Linus
From: Kalle Pokki <hidden> Date: 2016-06-15 22:42:53
Linus Torvalds [off-list ref] writes:
For example, a command like "git pull" will leave a special magic name
around to tell you what the original HEAD was before the pull, and that
magic name is (surprise surprise) called ORIG_HEAD. So if the pull
succeeded, but you realized it was an error (perhaps you had even intended
to do it, but once you pulled, you just saw that what you pulled was crap,
so you decide that you didn't really want to do it after all), you can
just do
git reset --hard ORIG_HEAD
and you're back to where you were _before_ the pull.
I usually undo a pull by throwing away just the merge commit by
git reset --hard HEAD^
This seems to always get me back to the head commit I had previously, but I'm
wondering would git in some circumstances leave me with the commits I just pulled
and throw away my own work instead. Or is it guaranteed that I always reset
to the parent commit I had before the pull (i.e. ORIG_HEAD)?
Of course HEAD^ doesn't work the same with fast-forward merges, so it would
probably make more sense to just use ORIG_HEAD all the time.
I usually undo a pull by throwing away just the merge commit by
git reset --hard HEAD^
Don't do this.
If the merge just fast-forwarded, you'll do the wrong thing.
So yes, it _works_, but it only works if you actually ended up having a
real merge. In contrast, the ORIG_HEAD thing always works.
ORIG_HEAD is also particularly useful for doing things like "ok, what did
I get from that pull?" especially when you track somebody elses work (in
which case it will basically _always_ be a fast-forward). So I do
gitk ORIG_HEAD..
in git almost every time I pull from Junio's git thing, just because it's
a wonderful way to see what has changed, if you're interested in that kind
of detail.
Linus
From: Bill Lear <hidden> Date: 2016-06-15 22:42:53
On Thursday, February 8, 2007 at 09:27:50 (-0800) Linus Torvalds writes:
On Wed, 7 Feb 2007, Bill Lear wrote:
quoted
I have a public bare repo on my machine that I have cloned to make a
private repo. I just want to sync my branches on my public and
private repos. I do not want to merge across branches, I just want to
"sync".
Ok, others already replied, but here's a few rules to ease your mind in
general:
- First off: you can always _trivially_ get back to whatever state you
had before, as long as you committed it, and didn't have any dirty
state (uncommitted patches) in your working tree.
...
Well, I have read all of the very welcome advice and am comfortable
with all of it.
However, I still have a few open issues with the other branch of this
discussion, i.e., why can we not have an update operation that
respects branches in the first place, as 'git pull' seems to do, when
run from the master branch? I do realize that the branch 'foo' in my
repo is different from the branch 'foo' in your repo. However, I want
to track things, and "track" here is a very appropriate word. Tracks
don't cross, and I don't want to cross my "logically equivalent"
branches (at least yet), even though, as Linus pointed out in great
detail, this is easy to undo (though, do see below for a qualification
of "easy").
So, why should I care?
Because, an ounce of prevention is worth a pound of cure. So, if a
pound of undo is so very easy, then, in my mind, an ounce of
preventing the problem in the first place is at least 1/16th that.
When working in a peer-to-peer relationship, I often push and pull
with my peers, perhaps on a daily basis, perhaps weekly. Just the
other day, my peer was the one who goofed up his branches and I pulled
them into my public repo, all tangled up, and did not realize it.
Thence pulled into my private repo, did lots of work, pushed back to
my public repo, and after more time intervened, realized something was
wrong. It took a LOT of work (for me, I'm sure for others here it
would have been much, much less) for me to 1) figure out the genesis
of the problem, and 2) figure out how to undo it all without
destroying my subsequent work. When we both do this, and merge
unexpectedly, at different points on one branch from a different
point on another, and then pollute each others' repos, it does become
rather ... well, annoying is the best way to put it.
In CVS, if I am on branch topic and say 'cvs update', it updates my
branch topic. If I am on branch master and say 'cvs update', it
updates my branch master. Etc., etc. It doesn't matter that you move
from one branch to the other, the update behavior is the same. In
git, if I am on master, things seem to work wonderfully --- one 'git
pull' and my entire repo is synced (that is, merged) as I expect with
the other repo.
I really don't want to do 'git fetch'. I really want 'git pull'. I
really want the changes put into my repo, from that repo's branch X
onto my branch X, and that repo's branch Y onto my branch Y. I really
don't want to have to remember to switch to my master branch before I
do git pull (this, however, as it stands, does seem to me to be the
best option). Perhaps I'll just write a script 'git-sync' that does
'git checkout master; git pull'...
Jakub is of course literally correct when he says "'Crossing of the
streams' is _required_ ... If you do parallel work ... you have to
do merges". Again, I recognize that my "foo" branch is different
from your "foo" branch, and that when they come together they are
in fact merged, but logically they are one thing --- one stream of
shared work that we don't want to slip over into another one, at
least not until we are ready.
Again, thanks to everyone for their patience. We really do enjoy
using git --- very cool, fast, and flexible.
Bill
From: Kalle Pokki <hidden> Date: 2016-06-15 22:42:53
Linus Torvalds [off-list ref] writes:
On Thu, 8 Feb 2007, Kalle Pokki wrote:
quoted
I usually undo a pull by throwing away just the merge commit by
git reset --hard HEAD^
Don't do this.
If the merge just fast-forwarded, you'll do the wrong thing.
Yes, I know. But when looking at the history with gitk, it feels
quite intuitive to just get rid of the one new commit that appeared
on top of the "good" history. Without that kind of visualisation
I would surely always just use ORIG_HEAD as a reference.
Perhaps gitk could (optionally) also show ORIG_HEAD. That way we could
just do
gitk --all
after a pull and see what got pulled, and everything else was already
there, too, if needed.
From: Shawn O. Pearce <hidden> Date: 2016-06-15 22:42:53
Kalle Pokki [off-list ref] wrote:
Perhaps gitk could (optionally) also show ORIG_HEAD. That way we could
just do
gitk --all
after a pull and see what got pulled, and everything else was already
there, too, if needed.
git config alias.new "gitk --all --not ORIG_HEAD"
Would give you a new git subcommand:
git new
which shows all of the new stuff, on all branches, but doesn't show
your prior commit history.
--
Shawn.
However, I still have a few open issues with the other branch of this
discussion, i.e., why can we not have an update operation that
respects branches in the first place, as 'git pull' seems to do, when
run from the master branch?
Actually, git does that all correctly for other branches too, but only in
git-1.5.
It's one of the bigger UI warts that got fixed since the last release
(although it got fixed by better config management, and as such you'll
only *see* the fixes if you end up doing the initial clone with the new
git version - if you use a new git version with an old repo, many - but
not all - bad semantics will remain).
Considering how stable the -rc kernels are (and actually, git "master" in
general), there's really very little reason to wait for the real release.
Junio has been very careful, and I think a lot of the delay in 1.5 has
been about trying to get all the new stuff that changes semantics subtly
in before the release, so that Junio will not have to do any real user-
visible changes later.
So it might be worth while trying out git-1.5.0-rc4, and seeing if that
solves some of the UI issues for you guys. It changes things like where
the default remote branches are, and makes the distinction between "my
local copy of branch X" and "the remote branch X" much clearer, which has
clearly been a UI problem.
Linus
From: Jakub Narebski <hidden> Date: 2016-06-15 22:42:53
Bill Lear wrote:
[cut]
With git 1.5.0-rc4 cloned repository, with globbing refspecs for origin
you don't have the problem. When you are on branch 'master', "git pull"
fetches and merges 'origin/master' into 'master'. When on any other
branch, "git pull" would fetch only (unless configured otherwise).
Note: you cannot pull into 'master' if you are not on 'master' because
of possibility of merge conflict: you need working area for that.
In CVS, if I am on branch topic and say 'cvs update', it updates my
branch topic. If I am on branch master and say 'cvs update', it
updates my branch master. Etc., etc. It doesn't matter that you move
from one branch to the other, the update behavior is the same. In
git, if I am on master, things seem to work wonderfully --- one 'git
pull' and my entire repo is synced (that is, merged) as I expect with
the other repo.
In CVS branches are totally f**ked up. And enforced update before commit
workflow doesn't help, also. Get rid of bad CVS habits. Please.
I really don't want to do 'git fetch'. I really want 'git pull'. I
really want the changes put into my repo, from that repo's branch X
onto my branch X, and that repo's branch Y onto my branch Y. I really
don't want to have to remember to switch to my master branch before I
do git pull (this, however, as it stands, does seem to me to be the
best option). Perhaps I'll just write a script 'git-sync' that does
'git checkout master; git pull'...
It's the only option.
Jakub is of course literally correct when he says "'Crossing of the
streams' is _required_ ... If you do parallel work ... you have to
do merges". Again, I recognize that my "foo" branch is different
from your "foo" branch, and that when they come together they are
in fact merged, but logically they are one thing --- one stream of
shared work that we don't want to slip over into another one, at
least not until we are ready.
So do fetch, and do pull only when changes are ready...
RTFM. Take a look at http://git.or.cz/gitwiki/GitLinks namely section
"Seminars and presentations", read new Git User's Manual also at
http://www.fieldses.org/~bfields/git-user-manual.html, browse GitWiki.
By the way, the workflow looks slightly different if you pull directly
from one another (A pulls or fetches from B, B pulls or fetches from A),
and if you have one central public bare repository (A pulls or fetches
from 'public' and pushes her changes to 'public', B pulls or fetches
from 'public' and pushes his changes to 'public'). In the latter git
asks you to pull (fetch) before pushing if you are not up to date. Notice
that it is on push, not on commit!
We should really update http://git.or.cz/gitwiki/GitWorkflows ...
but how to make diagrams: ASCII art is hard because it needs monospace,
upload of images attachements is not possible...
--
Jakub Narebski
Poland
From: Bill Lear <hidden> Date: 2016-06-15 22:42:53
On Thursday, February 8, 2007 at 14:13:47 (-0800) Linus Torvalds writes:
On Thu, 8 Feb 2007, Bill Lear wrote:
quoted
However, I still have a few open issues with the other branch of this
discussion, i.e., why can we not have an update operation that
respects branches in the first place, as 'git pull' seems to do, when
run from the master branch?
Actually, git does that all correctly for other branches too, but only in
git-1.5.
...
So it might be worth while trying out git-1.5.0-rc4, and seeing if that
solves some of the UI issues for you guys. It changes things like where
the default remote branches are, and makes the distinction between "my
local copy of branch X" and "the remote branch X" much clearer, which has
clearly been a UI problem.
Ok, very reasonable. I've been our corporate guinea pig, so I'll give
this a whirl. One thing I'm very, very happy about in git is the
ability to quickly experiment. Believe it or not, I have solved
actual git problems in our company by doing just that. Of necessity,
it's largely my complaints and problems that are aired here, though.
Bill
From: Bill Lear <hidden> Date: 2016-06-15 22:42:53
On Thursday, February 8, 2007 at 14:13:47 (-0800) Linus Torvalds writes:
...
It's one of the bigger UI warts that got fixed since the last release
(although it got fixed by better config management, and as such you'll
only *see* the fixes if you end up doing the initial clone with the new
git version - if you use a new git version with an old repo, many - but
not all - bad semantics will remain).
...
With regard to the new version and old repos, am I correct in assuming
that we can upgrade our old repo (a bare one) to the new git by first
installing the new git, and then doing this:
% cd /repos/git
% mv project project.old_git
% git --bare clone project.old_git project
or is there something else we must do?
Bill
From: Shawn O. Pearce <hidden> Date: 2016-06-15 22:42:53
Bill Lear [off-list ref] wrote:
With regard to the new version and old repos, am I correct in assuming
that we can upgrade our old repo (a bare one) to the new git by first
installing the new git, and then doing this:
% cd /repos/git
% mv project project.old_git
% git --bare clone project.old_git project
or is there something else we must do?
In the case of a bare repo, there isn't anything to do.
--
Shawn.
From: Jakub Narebski <hidden> Date: 2016-06-15 22:42:53
<opublikowany i wysłany>
Bill Lear wrote:
On Thursday, February 8, 2007 at 14:13:47 (-0800) Linus Torvalds writes:
quoted
...
It's one of the bigger UI warts that got fixed since the last release
(although it got fixed by better config management, and as such you'll
only *see* the fixes if you end up doing the initial clone with the new
git version - if you use a new git version with an old repo, many - but
not all - bad semantics will remain).
...
With regard to the new version and old repos, am I correct in assuming
that we can upgrade our old repo (a bare one) to the new git by first
installing the new git, and then doing this:
% cd /repos/git
% mv project project.old_git
% git --bare clone project.old_git project
% git clone --bare project.old_git project
although usually notation project.git is used, so I think it would be
% git clone --bare project.old_git project.git
"git --bare <cmd>" is equivalent to "git --git-dir=pwd". You want to make
bare clone "git clone --bare", not invoke git command in bare repository
"git --bare <cmd>": there is no repository yet!
You can just edit .git/config (prehaps generate it first
from .git/remotes/origin file using remotes2config.sh script from contrib
section), and move (rename) branches.
--
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git
From: Bill Lear <hidden> Date: 2016-06-15 22:42:53
On Thursday, February 8, 2007 at 18:33:24 (-0500) Shawn O. Pearce writes:
Bill Lear [off-list ref] wrote:
quoted
With regard to the new version and old repos, am I correct in assuming
that we can upgrade our old repo (a bare one) to the new git by first
installing the new git, and then doing this:
% cd /repos/git
% mv project project.old_git
% git --bare clone project.old_git project
or is there something else we must do?
In the case of a bare repo, there isn't anything to do.
So, I assume I need to tell our developers that once we have installed
the new git, they will need to set aside their old repos and just
clone again from our company repo?
Bill
With regard to the new version and old repos, am I correct in assuming
that we can upgrade our old repo (a bare one) to the new git by first
installing the new git, and then doing this:
% cd /repos/git
% mv project project.old_git
% git --bare clone project.old_git project
or is there something else we must do?
I would actually suggest against that. Why? Because it will set a new
"origin" (pointing to your old repo), and if you had something else
before, that's probably not what you want.
Anyway, for the *shared* repositories, the git-1.5 changes really don't
tend to make any difference anyway (since they don't even tend to really
_care_ about things like origin branches - they are just used to push and
pull from).
It's much more noticeable for the actual *development* repositories,
because they are the ones that have "origin" pointing to something else.
And yes, for those development repositories, it's usually a good idea to
just do
mv project old-project
git clone /repos/git/project
cd project
.. work work work ..
and be happy.
You can also set up the new configurations by hand in an old repository,
but there really doesn't tend to be a lot of reason to do that. Just as an
example: the above was _literally_ what I did myself, just because I was
too lazy to start editing .git/config files and setting things up in other
ways (renaming origin branches etc).
In fact, I just did it the other day for my "sparse" repository (which is
another project I started, but that is maintained by others these days).
So here's a snippet from my bash history:
...
837 mv sparse old-sparse
838 cat old-sparse/.git/config
839 git clone master.kernel.org:/pub/scm/linux/kernel/git/josh/sparse
...
(that "cat old-sparse/.git/config" was just because I had forgotten
exactly where the origin of that repo was, so I did that cat just to do a
cut-and-paste for the subsequent "git clone" ;^).
And yes, I did that just to get the nicer branch layout, something that my
old sparse git repo didn't have, because I had set it up with an old
version of git (and done some minimal manual maintenance).
Linus
From: Shawn O. Pearce <hidden> Date: 2016-06-15 22:42:53
Bill Lear [off-list ref] wrote:
So, I assume I need to tell our developers that once we have installed
the new git, they will need to set aside their old repos and just
clone again from our company repo?
Right. Otherwise they need to do the config changes by hand in their
existing repository, which may be annoying/tedious/painful/difficult,
depending on your knowledge level with git.
You can actually use the old developer repositories with the newer
Git without doing anything specific to upgrade them. Its just that
1.5.0 sets up the initial config of the repository differently,
and that's exactly the change in functionality you are looking for.
They can save their old topic branches (if they are important)
by doing something like:
mv proj old_proj
git clone git://server/proj proj
cd proj
git fetch ../old_proj topicA:topicA [topicB:topicB ...]
at which point ../old_proj can be tossed.
--
Shawn.
From: Jakub Narebski <hidden> Date: 2016-06-15 22:42:53
Bill Lear wrote:
On Thursday, February 8, 2007 at 18:33:24 (-0500) Shawn O. Pearce writes:
quoted
Bill Lear [off-list ref] wrote:
quoted
With regard to the new version and old repos, am I correct in assuming
that we can upgrade our old repo (a bare one) to the new git by first
installing the new git, and then doing this:
% cd /repos/git
% mv project project.old_git
% git --bare clone project.old_git project
or is there something else we must do?
In the case of a bare repo, there isn't anything to do.
So, I assume I need to tell our developers that once we have installed
the new git, they will need to set aside their old repos and just
clone again from our company repo?
Nope.
1. New git works with old repositories, and would continue to work.
Nevertheless you need new layout and new configuration to make use
of some new features.
2. They need to clone _their own_ repositories. It's the simplest
way, but
3. You can simply
a) convert remotes configuration from .git/remotes/origin file
to .git/config using remotes2config.sh script in contrib area
of git, or http://repo.or.cz/w/git.git?a=blob_plain;f=contrib/remotes2config.sh
b) hand edit remotes configuration to use globbing for refspec,
and per branch configuration
If old repository was _not_ cloned with --use-separate-remote (using
separate remote layout), you would also have to:
c) move branches from old layout to new layout using "git branch -m"
command: 'refs/heads/origin' branch to 'refs/remotes/origin/master',
all branches except 'master' (refs/heads/master) from
'refs/heads/<branch>' to 'refs/remotes/origin/<branch>'.
That's all. You have new layout and new configuration without re-cloning.
--
Jakub Narebski
Poland
So, I assume I need to tell our developers that once we have installed
the new git, they will need to set aside their old repos and just
clone again from our company repo?
Not unless they want to take advantage of *all* the new features.
The new version of git will work fine with old repositories, both on the
"server" side and the "user" side. And people can use a lot of the new
features even if they do nothing at all.
But for the _specific_ case of having a clearly separated "local branch"
vs "remote branch" case, you do need to make that distinction clear when
you create the repository (unless you want to get really down and dirty
with the repo and just modify it yourself: certainly possible but
generally just not worth the effort since it's just easier to clone a new
one instead).
So it's really a matter of how you use it. Switching to a new version of
git on the "server side" (ie the shared repository operations) won't
really affect anything at all.
Linus
On Thu, Feb 08, 2007 at 05:10:23PM -0500, Shawn O. Pearce wrote:
git config alias.new "gitk --all --not ORIG_HEAD"
Would give you a new git subcommand:
git new
which shows all of the new stuff, on all branches, but doesn't show
your prior commit history.
Aliases don't seem to be working for me; I'm using git 1.5.0-rc4. Am
I doing something wrong?
<tytso@candygram> {/usr/projects/linux/linux-2.6} [master]
37% git version
git version 1.5.0.rc4
<tytso@candygram> {/usr/projects/linux/linux-2.6} [master]
38% git config alias.new "gitk --all --not ORIG_HEAD"
<tytso@candygram> {/usr/projects/linux/linux-2.6} [master]
39% git new
git: 'new' is not a git-command
The most commonly used git commands are:
add Add file contents to the changeset to be committed next
apply Apply a patch on a git index file and a working tree
archive Creates an archive of files from a named tree
...
<tytso@candygram> {/usr/projects/linux/linux-2.6} [master]
40% tail .git/config
[user]
name = Theodore Ts'o
email = tytso@mit.edu
[remote "iwlwifi"]
url = http://bughost.org/repos/iwlwifi.git/
fetch = +refs/heads/*:refs/remotes/iwlwifi/*
[alias]
new = gitk --all --not ORIG_HEAD
From: Shawn O. Pearce <hidden> Date: 2016-06-15 22:42:53
Theodore Tso [off-list ref] wrote:
On Thu, Feb 08, 2007 at 05:10:23PM -0500, Shawn O. Pearce wrote:
quoted
git config alias.new "gitk --all --not ORIG_HEAD"
Would give you a new git subcommand:
git new
which shows all of the new stuff, on all branches, but doesn't show
your prior commit history.
Aliases don't seem to be working for me; I'm using git 1.5.0-rc4. Am
I doing something wrong?
Its not you. The problem is 'gitk' is not an internal command,
nor is there a 'git-gitk'. So we cannot execute it. Instead we
are giving back a horrible error message.
Symlink git-gitk to gitk and it works.
Sorry about giving false hopes. :-)
--
Shawn.
From: Jakub Narebski <hidden> Date: 2016-06-15 22:42:53
<opublikowany i wysłany>
Theodore Tso wrote:
On Thu, Feb 08, 2007 at 05:10:23PM -0500, Shawn O. Pearce wrote:
quoted
git config alias.new "gitk --all --not ORIG_HEAD"
Would give you a new git subcommand:
git new
which shows all of the new stuff, on all branches, but doesn't show
your prior commit history.
Aliases don't seem to be working for me; I'm using git 1.5.0-rc4. Am
I doing something wrong?
<tytso@candygram> {/usr/projects/linux/linux-2.6} [master]
37% git version
git version 1.5.0.rc4
<tytso@candygram> {/usr/projects/linux/linux-2.6} [master]
38% git config alias.new "gitk --all --not ORIG_HEAD"
<tytso@candygram> {/usr/projects/linux/linux-2.6} [master]
39% git new
git: 'new' is not a git-command
Actually I think you can only alias git commands. For example
"alias.last = cat-file commit HEAD" makes "git last" call
"git cat-file commit HEAD".
So "alias.new = gitk --all --not ORIG_HEAD" would mean that
"git new" invokes "git gitk ..." not "gitk ...". Do you see
the problem.
But error message is a bit strange...
--
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git
From: Michael S. Tsirkin <hidden> Date: 2016-06-15 22:42:53
So, I assume I need to tell our developers that once we have installed
the new git, they will need to set aside their old repos and just
clone again from our company repo?
Hint:
If a developer has some relevant data in his old private repository, he can always
pull from old to new repository there after he clones from the public repository.
This way you won't lose any data in the conversion.
--
MST
From: Kalle Pokki <hidden> Date: 2016-06-15 22:42:53
"Shawn O. Pearce" [off-list ref] writes:
git config alias.new "gitk --all --not ORIG_HEAD"
Would give you a new git subcommand:
git new
which shows all of the new stuff, on all branches, but doesn't show
your prior commit history.
Yes, but what I meant was that gitk wouldn't stop at ORIG_HEAD,
but just display it as another branch head with a nice green tag.
Normally, displaying ORIG_HEAD would probably not be interesting,
but it might make sense with
gitk --all
It would give more context to the pull than just
gitk ORIG_HEAD..
If the alias expansion is prefixed with an exclamation point, treat
it as a shell command which is run using system(3).
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
---
Documentation/config.txt | 6 ++++++
git.c | 10 ++++++++++
2 files changed, 16 insertions(+), 0 deletions(-)
@@ -222,6 +222,12 @@ alias.*:: spaces, the usual shell quoting and escaping is supported. quote pair and a backslash can be used to quote them.+ If the alias expansion is prefixed with an exclamation point,+ it will be treated as a shell command. For example, defining+ "alias.new = !gitk --all --not ORIG_HEAD", the invocation + "git new" is eqvuialent to running the shell command + "gitk --all --not ORIG_HEAD".+ apply.whitespace:: Tells `git-apply` how to handle whitespaces, in the same way as the '--whitespace' option. See gitlink:git-apply[1].
@@ -159,6 +159,16 @@ static int handle_alias(int *argcp, const char ***argv)alias_command=(*argv)[0];git_config(git_alias_config);if(alias_string){+if(alias_string[0]=='!'){+trace_printf("trace: alias to shell cmd: %s => %s\n",+alias_command,alias_string+1);+ret=system(alias_string+1);+if(ret>=0&&WIFEXITED(ret)&&+WEXITSTATUS(ret)!=127)+exit(WEXITSTATUS(ret));+die("Failed to run '%s' when expanding alias '%s'\n",+alias_string,alias_command);+}count=split_cmdline(alias_string,&new_argv);option_count=handle_options(&new_argv,&count);memmove(new_argv-option_count,new_argv,
Its not you. The problem is 'gitk' is not an internal command,
nor is there a 'git-gitk'. So we cannot execute it. Instead we
are giving back a horrible error message.
Here are some patches to fix the horrible error message and to allow
aliases to expand to external shell commands.
- Ted
@@ -387,8 +387,15 @@ int main(int argc, const char **argv, char **envp)done_alias=1;}-if(errno==ENOENT)+if(errno==ENOENT){+if(done_alias){+fprintf(stderr,"Expansion of alias '%s' failed; "+"'%s' is not a git-command\n",+cmd,argv[0]);+exit(1);+}help_unknown_cmd(cmd);+}fprintf(stderr,"Failed to run command '%s': %s\n",cmd,strerror(errno));
If the alias expansion is prefixed with an exclamation point, treat
it as a shell command which is run using system(3).
ACK. This should also make it possible to do pipelines etc as aliases,
although to be *really* useful we would probably have to have some way to
specify where the arguments to the alias would go.
The more generic solution is obviously to just do it as external shell
scripts (which can be named "git-xyzzy" so that you don't even need this
kind of thing), but for the simple cases like gitk/qgit/xmerge/whatever,
this approach by Ted seems to be a good way to get easy access to stuff
that doesn't need anything fancier..
Linus
Here's a revised patch which fixes a stupid spelling typo in the
documentation. ("eqvuialent" --> "equivalent")
From c16544aa786b0fb244fd974a22831a1210286ec5 Mon Sep 17 00:00:00 2001
From: Theodore Ts'o <tytso@mit.edu>
Date: Sat, 10 Feb 2007 10:50:58 -0500
Subject: [PATCH] Allow aliases to expand to shell commands
If the alias expansion is prefixed with an exclamation point, treat
it as a shell command which is run using system(3).
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
---
Documentation/config.txt | 6 ++++++
git.c | 10 ++++++++++
2 files changed, 16 insertions(+), 0 deletions(-)
@@ -222,6 +222,12 @@ alias.*:: spaces, the usual shell quoting and escaping is supported. quote pair and a backslash can be used to quote them.+ If the alias expansion is prefixed with an exclamation point,+ it will be treated as a shell command. For example, defining+ "alias.new = !gitk --all --not ORIG_HEAD", the invocation + "git new" is equivalent to running the shell command + "gitk --all --not ORIG_HEAD".+ apply.whitespace:: Tells `git-apply` how to handle whitespaces, in the same way as the '--whitespace' option. See gitlink:git-apply[1].
@@ -159,6 +159,16 @@ static int handle_alias(int *argcp, const char ***argv)alias_command=(*argv)[0];git_config(git_alias_config);if(alias_string){+if(alias_string[0]=='!'){+trace_printf("trace: alias to shell cmd: %s => %s\n",+alias_command,alias_string+1);+ret=system(alias_string+1);+if(ret>=0&&WIFEXITED(ret)&&+WEXITSTATUS(ret)!=127)+exit(WEXITSTATUS(ret));+die("Failed to run '%s' when expanding alias '%s'\n",+alias_string,alias_command);+}count=split_cmdline(alias_string,&new_argv);option_count=handle_options(&new_argv,&count);memmove(new_argv-option_count,new_argv,
@@ -159,6 +159,16 @@ static int handle_alias(int *argcp, const char ***argv)alias_command=(*argv)[0];git_config(git_alias_config);if(alias_string){+if(alias_string[0]=='!'){+trace_printf("trace: alias to shell cmd: %s => %s\n",+alias_command,alias_string+1);
Here, you add 1 to alias string (though I would put spaces around the
plus, but that's really a nit).
+ ret = system(alias_string+1);
+ if (ret >= 0 && WIFEXITED(ret) &&
+ WEXITSTATUS(ret) != 127)
+ exit(WEXITSTATUS(ret));
+ die("Failed to run '%s' when expanding alias '%s'\n",
+ alias_string, alias_command);
So, shouldn't you here, too?
It made me feel a little uneasy that we can execute _any_ command now, but
I can only find one way to exploit this, when an attacker does not have
shell access anyway: git-shell.
Ciao,
Dscho
On Sat, Feb 10, 2007 at 09:34:38PM +0100, Johannes Schindelin wrote:
quoted
+ if (alias_string[0] == '!') {
+ trace_printf("trace: alias to shell cmd: %s => %s\n",
+ alias_command, alias_string+1);
Here, you add 1 to alias string (though I would put spaces around the
plus, but that's really a nit).
That's not how I code but it does seem to be the prevailing git coding
style, so I'll change it.
quoted
+ die("Failed to run '%s' when expanding alias '%s'\n",
+ alias_string, alias_command);
So, shouldn't you here, too?
Yes, that makes the error message look a bit nicer. I'll respin the
patch.
It made me feel a little uneasy that we can execute _any_ command now, but
I can only find one way to exploit this, when an attacker does not have
shell access anyway: git-shell.
... and git-shell only allows git-receive-pack and git-upload-pack to
be called, with a single argument, and aliases aren't allowed to
override commands. So we're safe here, I think.
- Ted
From: Johannes Schindelin <hidden> Date: 2016-06-15 22:42:53
Hi,
On Sat, 10 Feb 2007, Theodore Tso wrote:
On Sat, Feb 10, 2007 at 09:34:38PM +0100, Johannes Schindelin wrote:
quoted
It made me feel a little uneasy that we can execute _any_ command now,
but I can only find one way to exploit this, when an attacker does not
have shell access anyway: git-shell.
... and git-shell only allows git-receive-pack and git-upload-pack to be
called, with a single argument, and aliases aren't allowed to override
commands. So we're safe here, I think.
Yes, sorry. I have a modified git-shell, which allows the git wrapper,
too, to allow setting the config. I'll just fix it here.
Ciao,
Dscho
On Sun, Feb 11, 2007 at 05:03:29PM +0100, Johannes Schindelin wrote:
quoted
... and git-shell only allows git-receive-pack and git-upload-pack to be
called, with a single argument, and aliases aren't allowed to override
commands. So we're safe here, I think.
Yes, sorry. I have a modified git-shell, which allows the git wrapper,
too, to allow setting the config. I'll just fix it here.
If all you've enabled is the ability to set the config, I think we're
still safe, since aliases can't override commands.
Still there are enough config options that might be scary, either now
(the http.ssl* options) or in the future (someone might think that it
makes sense to set the post-commit, post-push, et. al hooks in the
config), that I wouldn't be particularly comfortable letting git-shell
have unrestricted access to set the config without having some
restriction about which config parameters were allowed to be set from
the restricted shell. Why did you add that ability, out of curiosity?
- Ted
From: Johannes Schindelin <hidden> Date: 2016-06-15 22:42:53
Hi,
On Sun, 11 Feb 2007, Theodore Tso wrote:
[I was talking about my local git-shell being allowed the git wrapper,
to set config variables]
Why did you add that ability, out of curiosity?
It seemed a good idea to make the description for gitweb a config
variable, and I wanted the users to change that themselves. It no longer
seems a good idea, so I will probably just undo my changes.
Ciao,
Dscho