Reputation: 33583
I'm using git, but I'll be glad to hear answers relevant to other SCMs.
I'm having a few small changes which are relevant just for me (using a different build scheme, relevant only for my configuration), and I really need to have them.
The right thing to do is of course, merge it into the trunk, but until I'll merge it into the trunk I have to keep a list of changes which will not be committed.
So let's say I'm need to change my makefile to have CC=mygcc
(since I need the gcc symlink pointing to a bad version for other software I'm compiling), but I don't want to commit it (others don't, so others don't want to have mygcc
symlink).
What do I do to allow me easily synchronize and update the main repository?
Upvotes: 2
Views: 165
Reputation: 62168
In Mercurial, this is best done with an mq patch.
To make the initial patch:
cd <working copy>
hg qinit
...make changes to your working copy
hg qnew <patch_name>
Then, when it is time to pull changes from the remote or actually commit new local changes:
hg qpop -a # remove all patches from your working copy
hg pull --update # get new changesets from the remote and update to the latest
...work on local files
hg commit -m "commit changes without touching the patch"
hg push # send changes to a remote repo that don't include the patch
hg qpush -a # apply all patches to your updated working copy
Upvotes: 3
Reputation: 33583
In git
I see 2 options:
git add -p
, wait, do I need that line...).Let me show a quick script I've written in order to make sure your temporary commit is alway. I assume that the temporary commit will have #alwaysontop
in the commit message.
This script basically searches for the first reachable commit with #alwaysontop
in the commit message and rebase all changes after it so that it'll be on top. Make sure there are no conflicts with your commits and the #alwaysontop
one, otherwise it will not work nicely.
You should make sure you never push a commit marked with #alwaysontop
with pre-push hook.
#!/bin/sh
if ! git diff-index --quiet HEAD --; then
echo "Repository is dirty, only run with clean index and working tree"
exit -1
fi
KEYWORD=':/#alwaysontop'
if ! git rev-parse $KEYWORD &>/dev/null; then
echo No commit with $KEYWORD found
exit -1
fi
TEMPREV=`git rev-parse $KEYWORD`
REMOTE_BRANCH=`git rev-parse $TEMPREV^`
echo @ rebasing current commit before $TEMPREV
git rebase --onto $REMOTE_BRANCH $TEMPREV && \
NEWHEAD=`git rev-parse HEAD` && \
echo @ now at $NEWHEAD moving to always-on-top commit && \
git reset --hard $TEMPREV && \
echo @ rebasing $TEMPREV to be topmost && \
git rebase $NEWHEAD
Upvotes: 2
Reputation: 467033
This is really a comment on Elazar Leibovich's second option which became a bit out-of-hand for a comment :) In commit graph terms, I would basically do the same as option 2, but maintain a local branch which has my changes rather than staying on master. In other words, the usual state would be like this:
A --- B --- C (master,origin/master) --- D --- E (local)
... if I want to update from master, I would do:
git checkout local
git fetch origin
git rebase origin/master
... to get to:
A --- B --- C (master) --- F --- G (origin/master) --- D' --- E' (local)
If I'd added more commits onto local
, I'd make that a git rebase -i origin/master
so that I can make sure that my D
and E
are still most recent in the history.
The advantage of this over Elazar Leibovich's option 2 is just that it reduces the risk that you're going to accidentally push your local changes to master
with git push
or git push master
, since your local changes will never be on the master
branch and there should be no branch called local
remotely. (If there is, choose a different name, obviously :))
When you do have something you want to push back to master
, for example the commits H
and I
here:
A -- B -- C (master) -- F -- G (origin/master) -- H -- I -- D'' -- E' (local)
... you would do:
git checkout master
git merge I
git push origin master
Upvotes: 4