git - Add some subdirectories to the local repo but not to remote?
Is there a (relatively) simple way to add some parts of the tree to the local repository but NOT to the remote repository? For example, suppose I have something like
project_root/
-- src/ <- in local and remote
-- test/ <- in local and remote
-- my_dev_ideas/ <- c开发者_JAVA技巧urrently untracked, want in local but not remote
I would like to add my_dev_ideas/
so that I can keep track of it in my local repo but not include it when pushing to remote. I could create a branch and my_dev_ideas/
in the branch, but there are a couple hangups:
- When I try to merge back into (for example) master, I don't want it to create a
my_dev_ideas/
- This is a simplified example - in reality it's a fairly large project and I have a handful of such directories scattered throughout the tree.
- IMO it breaks the abstraction of what a "branch" is. I still want to be able to create local branches like
add-feature
that still have these directories in them locally.
I've seen some similar questions but not a great answer. I don't really want to use submodules because there are multiple directories involved and because I want the local repo history to reflect changes to files in these directories. That is, unless there's a simple way to do just that.
I'm hoping the following might work to my advantage.
- The directories aren't already in the repo (local or remote).
- I don't necessarily need to cherry-pick specific files - just parts of the directory tree.
I understand why this could be very complicated or even impossible, (suppose I change src/foo.cpp
and my_dev_ideas/bananas.h
in the same commit...) but I wanted to see if anyone had any suggestions anyways..
this sounds like a job for git submodules that way you can track them seperatly. though this means you have to go to the trouble of linking the two projects which may just git you a different kind of trouble. perhaps it will help?
(Yes, I realize this is over a year old. But I'm dealing with something similar, so let me share my thoughts in hopes it helps someone).
Well, you can do it. There are several approaches, but they're all complicated. But I think this will prove simplest:
Bringing in changes from outside your repository isn't a problem (assuming nobody adds the same files you do locally). Just merge or rebase as usual. But publishing without your files is a bit trickier.
First, you'll want to locate the earliest commit where you added the stuff you don't want to publish. Let's say thats 1abcdef. We really want the parent of that commit, so let's create a branch to refer to it:
git branch before_publish 1abcdef^
Note carefully the ^ at the end of the line. If you're using windows and cmd.exe, you'll have to quote it with a second ^ character, i.e. ^^, as cmd.exe uses ^ as the line continuation character....
Next, let's create and check out a branch to publish (assuming we've already checked out the branch we want to publish from):
git checkout -b publish
Now's the fun part. We want to rid this branch of the offending files.
git filter-branch -f --index-filter 'git rm -r -f --quiet --cached --ignore-unmatch <your list of files and directories here>' before_publish..publish
OK, this gives you a branch without the additions you don't want to publish. You can then merge or rebase these changes on top of the main branch you started from, and push them however you normally would, according to your workflow.
Note that this may leave your working tree with some remnants -- empty directories, or directories containing files that were excluded or untracked. But they're gone from the branch.
The final step, of course, is to check out your original working branch again.
The next time, you can repeat the process -- but you could also merge in just the changes made since. To facilitate this, you might move before_publish to point to your current head of publish, and add a branch to track where you last merged from on your working branch.
You won't directly be able to use 'git merge' -- you'll have to use:
git checkout publish
git branch -f before_publish
git cherry-pick last_published..my-main-branch
git filter-branch ... before_publish..publish
git checkout my-main-branch
git branch -f last_published
It's a little more complicated, but it saves you from having to repeatedly create new commits for the entire history of your additional files. It's probably not worth doing if you are doing something short-lived.
You can also do this to undo deletions! Rather than doing 'git rm', use its opposite, git reset. You'll use it to pull in the missing files and directories from when they still existed:
git filter-branch -f --index-filter 'git reset --quiet before_publish -- <paths to restore>' before_publish..publish
Of course, you can (and should) combine both in a single 'git filter-branch' operation if you need both.
精彩评论