Some git repository manipulations that I don't know how to do well
For a while now, I've been both tracking upstream git repositories and carrying and rebasing local changes on top of some of them in a straightforward way. The rebasing has been pretty easy and a clear win. But recently I've run into a number of more complicated cases where I'm not sure that I'm using git in the best way. So here are a collection of problems that I'm semi-solving.
I keep local tracking copies of a few upstream repos that are rebased
periodically, such as this one.
I have no local changes in such tracking repositories (ie my local
master is always the same as
origin/master). When the upstream
rebases my plain
git pull will fail, either telling me that it
can't be fast-forwarded or demanding that I merge things. In the
past I've just deleted the entire repo and re-cloned as the simple
way out. Recently I've constructed the manual fix:
git pull --ff-only [fails, but it's fetched stuff] git checkout -f -B master origin/master
It would be nice to have the repo set up so that a plain '
pull' would do this, ideally only if it's safe. I could script
this but there are only some repos that I want to do this for; for
others, either I have local changes or this should never happen.
git pull manpage has some interesting wording that makes it
sound like asking for a rebase here will maybe do the right thing.
But I just found that and contriving a test case is not trivial.
Or maybe I want '
git pull -f'. And now that I've done some web
searches, apparently I want '
git reset --hard origin/master'.
Git is like Perl; sometimes it has so many different paths to the
Next, I'm tracking the repo for my favorite RAW development software and have some little local fixes added on top. Normally I build from the latest git tip, but that's sort of in flux right now so I want to switch to the release branch but still add my changes on top. I'm doing this like so:
git checkout darktable-2.0.x git cherry-pick origin/master..master
I think that using
git cherry-pick here instead of some form of
git rebase is probably the correct approach and this is the one
case where I'm doing things right.
I'm tracking the main repository for my shell and applying my changes on top of
it. However, there is a repository of interesting changes that I want to try out; of course
I still want my local changes on top of this. When I did this I
think what I did was '
git pull --rebase /the/other/repo', but I
believe that probably wasn't the right approach. I suspect that
what I really wanted to do was add the second repo as an alternate
upstream, switch to it, and either cherry-pick or rebase my own
changes on top.
Except, well, looking back at my notes about working with Github PRs it strikes me that this is basically the same situation (except this repo isn't an explicit PR). I should probably follow the same process instead of hacking my way around the way I did this time.
Finally, we combine the two situations: I'm building on top of the repo of interesting changes and it rebases itself. Now I want to replace the old version with the new version but reapply my changes on top. I'm not going to try to write down the process I used this time, because I'm convinced it's not optimal; I basically combined the reset origin plus cherry-pick process, using explicit commit hashes for the cherry-picking and recording them beforehand. Based on Aristotle Pagaltzis's comment on my Github PR entry, I think I want something from this Stackoverflow Q&A but I need to read the answers carefully and try it out before I'm sure I understand it all. It does look relatively simple.
(This writeup of
git rebase --onto is helpful too,
but again I need to digest it. Probably I need to redo this whole
procedure the right way the next time this comes up, starting from
a properly constructed repo.)
Sidebar: How I test this stuff out
I always, always test anything like this on a copy of my repo, not
on the main version. I make these copies with
making repo copies with '
git clone' changes how git sees things
like upstreams (for obvious reasons). I suspect that this is the
correct approach and there is no magic '
git clone' option that
does what I want here.