0

it's a pretty new thing to me. We have admitted our customer to get access to our source code. Using bitbucket/Sourcetree i meant to use a Fork to grant him read Access to a given state/commit. I don't want to grant access to actual (still in development code). I plan to share milestones only. Can Forks be used in this manner? Are there other options to share particular commits only? BR, Daniel

Louis Langholtz
  • 2,391
  • 3
  • 13
  • 34
dba
  • 712
  • 1
  • 11
  • 20
  • [This answer](https://stackoverflow.com/questions/19641108/split-git-repo-in-a-squashed-public-and-initial-private) might be what you're after, you just have to be sure to always squash-merge-and-null-merge-back when extending the public branch. – jthill Apr 05 '17 at 19:58

2 Answers2

0

For what I think you want to do, the simplest way would be this:

  1. checkout commit you want to share;
  2. copy project directory under another name (excluding .git hidden dir);
  3. import that copied project directory as a new git repo (on github, bitbucket or wherever). Or zip it and send to the client directly.

This way, client will see a snapshot of your code. No current commits and no history.

Sergio Tulentsev
  • 210,238
  • 40
  • 347
  • 343
  • Hi, thank you, I will consider your Suggestion. I like the historyfree Part of this solution – dba Apr 05 '17 at 16:57
0

I don't believe there's a way to provide commit- or branch-level access control within a repo. Creating a more limited repo is a reasonable approach, but depending on your needs I would possibly suggest some alternatives to copying the snapshot in the way Sergio Tulentsev suggests.

The potential downside to that is the loss of any data that would internally connect the shared snapshot back to your history. If you might provide new versions in the future, or if you might accept patches from the fork back into your codebase, then this separation creates additional work.

Part of the solution is simply keeping track of the relationships between your commits (with history) and their commits (provided snapshots); and that part of the problem you could solve just with a tagging convention of some sort. But beyond that, if you think you might want to migrate changes back and forth then you can set things up to avoid some manual migration work.

So you could try something like this:

First, in your repo, identify the commit you initially want to share and create a branch for the fork. If you have the commit tagged as commit-to-be-shared then

git checkout commit-to-be-shared
git checkout -b fork_master

(Or maybe the customer's name instead of fork-master, if you think this is something you might do again for someone else...)

Next, instead of manually copying to a new repo, make a "shallow clone" of your origin. Note that you must use a URL (not a local path); so if you normally address the repo as /path/to/my/repo use something like file://path/to/my/repo... details depend on your OS, but hopefully you see what I mean...

cd ..
git clone --depth=1 -b fork-master http://my.server/origin-repo

This will only copy the one commit, and will set up fetch to only retrieve the fork-master branch. But, it will preserve the identity of the commit. So in your origin, in the future you could merge more changes into fork-master and easily share the resulting commit. BUT if/when you do push more changes, see below for notes on avoiding unintentional history exposure.

Next you prepare an empty repo on your server (along side your origin) which will serve as the customer's origin. Then set it up as a second remote in your newly created shallow repo:

git remote add fork-origin http://my.server/fork-origin-repo
git push -u fork-origin master

(Again you could use a customer-specific name for the remote if you think you might have more later...)

Any of your developers can add fork-master too if you want to allow it, and in this way you can seamlessly receive patches from the customer.

There is a trick to ensuring you don't inadvertently expose history in the future, though. When you make a future merge to fork-master and deliver it to the fork-origin, by default it would bring the history of the newly-merged commit. The apparent simple fix is, in your shallow repo:

git pull --depth=1

The problem here is that git can become confused. (Short explanation is that the newly-fetched merge is meant to have depth 1 on the 2nd parent but not on the first, and git doesn't seem to handle that the way you might hope.) Not too hard to solve:

git pull --depth=2

Now you'll see, though, that the merge brought one extra commit of history from the newly-merged-in work. That commit just contains the changes you're merging in to fork-master so it probably is ok; but maybe that commit has a commit message, or tags, or something else that you don't necessarily want to share. In that case, you could always create a sort of "buffer commit" just before the merge.

    F1 -------- F2 <--(fork-master)
    /           /
   /           B
  /           /
X ---- X --- A --- X <--(master)

where F1 is the original shared snapshot, A contains more changes you've decided to share, B is a "customer-safe" commit that essentially duplicates A, and F2 is the new merge. Then the customer would see

F1 ---- F2
       /
      B

You may have to use the --allow-empty option when calling git commit to create B.

Note I haven't had a chance to test this end-to-end; if you get errors at any step please let me know so I can update accordingly.

Mark Adelsberger
  • 32,904
  • 2
  • 24
  • 41
  • Hello Mark, thank you for this great explanation. In my case there will be no commits on customer side. They only need the source to be available on their site as a private backup. There is no common work intended in any way. Actually the suggestion of @SergioTulentsev is what I need, a history-free repo (as particular commits cannot be shared). I just wanted to use forks for this due the easier workflow on my side. So the question is, can it be used in this manner, can I clean up this forked repo history with no impact on working repo? – dba Apr 06 '17 at 17:16
  • The plan is to share separate forks on reaching a milestone, and never update the pervious state(fork) – dba Apr 06 '17 at 17:24
  • As I said, the approach depends on your need. I see a lot of times people jump to approaches like "copy the tree to a new repo" without considering commit identity, so spelled out an alternative in case that matters. But if it doesn't, then copying the tree to a new repo should be fine. Either way, the reason we've both spelled out ways to create a new repo is that the answer to your direct question - can you get there just by making a fork? - is no (unless your server has special functionality to automate one of these approaches when forking, which I've never seen). – Mark Adelsberger Apr 07 '17 at 13:54