I wanted to try this out but don't know if it's possible. Usually, to prevent files/folders from being tracked by git and also pushed to the remote from the local, you would add a .gitignore
file - gitHub doc.
I'm asking for the other way round. Is there a file, config or settings for ignoring files/folders in the remote repository and preventing download to local?
1st paragraph edited thanks to @IMSoP's response.
CodePudding user response:
No: as already noted, Git works on a commit-by-commit basis, and when you use git clone
or git fetch
,1 you obtain the commits from the other Git. Those commits contain the files that they contain, as a snapshot.
Yes: once you have commits from some other Git repository in your repository, you can extract individual files from these commits. There's no automatic way to do this, but you can set up your own scripts. Be careful about it because some Git operations will read an entire commit and populate your working tree with lots of unwanted files.
Your best bet is probably to clone the repository somewhere else and then bring over the files of interest.
1Although the code is built into the clone
command directly, git clone
uses git fetch
, so to some extent this is redundant.
CodePudding user response:
This isn't a standard workflow, so there's no convenience commands for it. You can get Git to do this, it's even fairly easy once you've got the "extensible dag of immutable snapshots, with labels on" mantra down cold, but all the convenience commands are set up to expect a full history in reach so you generally have to avoid them and replace them with the (very few) core commands each invokes for you.
Just to be clear: see the Git docs for the commands I'm using, and git help revisions
for the revision syntax like @{U}
aka @{u}
aka @{upstream}`. Turns out you can do everything a dvcs needs to do with an extensible dag of immutable snapshots, with labels on, if you maintain an index of the pieces in any current snapshot being viewed or constructed. Imagine Gary Oldman yelling "everything!". E v e r y t h i n g Git does is extending, analyzing, and schlepping around bits of that dag. The structure itself is bone stupid. What you can do with it, is not.
Let's take the aosp platform base repo and say you want to look at the core
directory, the full history is big enough to be painful for casual cloning and so if you're exploring you might want to see just part of it.
That much is almost cookie-cutter easy:
git clone -n --filter=tree:0 https://github.com/aosp-mirror/platform_frameworks_base.git
cd !$:t:r # history expansion for `cd platform_frameworks_base`
git read-tree -um @:core
and you have now fetched the barest sketch of the entire history, and only the latest copy of only the core
directory.
If you just wanted to look, you're done¹. For patch work on what you've got checked out, all the usual convenience commands that deal with commits will need replacing by short core-command "no no do just this part really" sequences, like the read-tree above instead of the usual checkout the -n
switch told git clone
not to do.
Just to have something concrete to talk about, let's say you've got some doc fixes to do that only touch this directory, or we could imagine that this really is a separable history that just hasn't been officially separated for whatever reason, and you want to carry patches on it. Whatever.
First up: let's do this on a mystuff branch:
git checkout -b mystuff # new name for the current work
git branch -u master@{u} # tracking whatever the master branch tracks
Next, git commit
is a convenience command that, for your convenience, prints a summary of what changed from the parent commit, which is good to have when you're composing a commit message but means it'll fetch whatever parts of the current commit you just went to some small effort not to fetch. But you really don't want to have to avoid git commit
forever, so let's tell git what we're up to just this first time:
git reset --soft $(git commit-tree -p @ -m mystuff @:core)
git tag mystuff-base
and after further git commit
s can proceed normally, everything the convenience command expects is all set up.
You can push your cut branch anywhere, but when people merge with it they'll need to specify the -Xsubtree
(or -Xsubtree=core
, Git's good at figuring this out but you can just tell it what subtree you mean) merge option, because as I said this is not a standard workflow and Git
by default won't spend any effort looking for possible hoist/splice points like this.
If you want to bring your own branch up to date with the latest master tip, an ordinary git merge
will look at that latest master tip and the merge base. The whole of both commits. Which you don't want. To avoid that,
git fetch # honors the filtering set up by that `git clone` above
git merge $(git commit-tree -p mystuff-base -p @{u} -m 'core slice' @{u}:core)
git tag -f mystuff-base
and that's really all there is to it: you now know enough to fetch, merge and push just the content you're working with, and only the parts you really need to look at.
¹ If you were just looking at the one subdirectory and that's all, you could even add --depth=1
to the clone to get not even a sketch of the full history