How to keep a file private to a Mercurial repository? - version-control

I like to keep a file with some private data (links, etc) in the project that I'm working on. I liked to be versioned but not exportable (by push) to other repository.
Below is a more schematic description of my problem.
I cloned a repository (r) to my repository (m)
I added a file to my repository (m) that I do not want to push to initial repository (r) but I want it tracked in my repository (m). It's a file where I keep links, etc.
How can I push to initial repository (r) but ignoring the file from my repository (m)?

Mercurial pushes changesets, not files.
If you ask Mercurial to start tracking a file by adding it, and then committing it, it is now part of the history of the repository.
Pushing from this repository, will push that file as well.
Summary: Don't do it, it can't be done. Find a different way to handle this situation.

Read about Mercurial Queues
Just store creating file with all private content in mq-patch (or only private data in patch and file-skeleton in repo)

You could create a new repository in your m repository, and put all your files into that. mercurial ignores repositories inside repositories, unless you include them via the subrepo extension.
cd m
hg init local
cd local
echo "my stuff" > info.txt
cd ..
hg st
# does not show files in local
cd local
hg ci -A -m "first commit"
cd ..
hg log -l 2
# does not show commit in local
A better solution in my opinion is to create a repository that lives besides the m repository. It's cleaner and more difficult to mess it up.

Related

Unified updates : Update private repo with updates from local files(refactored, renamed, updated) & get regular updates from original repo

I have just started learning to us GitHub CLI tool on Windows. Consider me a newbie
I have a use case that looks like this :
Let me summarize before i go a little deep:
My use case is : Cloning an open source project (which updates
regularly), i.e create a local copy of it and make modifications(including
renaming files and folders), pushing the changes to my private repo
but at the same time I require regular updates from the open source
project reflected in renamed format. Do i have to rename the files &
folder every time the project releases an update and push it to my
private repo ?
Lets say Project A is an open source project that regularly updates its files. Project B is my private repo on GitHub. All the initial steps for linking my Project C(local repo) to Origin(Project B) & Upstream(Project A) have been completed through the cli and config file inside .git folder.
On my computer , My local copy Project C has been obtained by using the command
git clone "https:..../project-B.git"
Now my purpose is the following :
1.To make heavy customizations to the code itself in my local copy Project C on my computer and push those changes to my private copy: Project B. This includes but not limited to renaming the project folders and files.
2.To obtain regular updates from Project A and the same needs to be updated in the private repo Project B.
In short, My private repo project B should have my changes and the regular changes that happen from the upstream end: project A
What's the best approach to achieve this?. I'm aware of the following steps to Push my local copy into Private Repo B :
Step 1 : git status -->to check for the changes in local copy.
Step 2 : git add --all
Step 3 : git commit -m 'message reflecting the nature of change'
Step 4 : git push -u origin master
where origin is my Private repo B and master is the branch that contains all the files.
I'm also aware of pulling in the upstream files by using :
git pull upstream master --> to pull in the latest changes from project A onto project B.
My Question is therefore :
1.When exactly should I Use git pull or git rebase with find renames : Before or after I push the committed changes. My limited understanding is git rebase is to find renamed files in origin(in my use case) and make the changes ?
Or
2.I need an entirely different approach?
Or
3.An approach to the above with minor shifts?
EDIT:
I have successfully pushed my local changes (project C-> project B(private repo on on git) using the command git push -u origin master.
Only, I need to know how can I pull changes from repo Project A(open source which regularly updates) and update my current local copy which is already renamed(folder, files everything else) & other new lines of code that is added. Eventually I need to push those updated changes from Project C(local copy)--->Project B(private repo) and have my private repo UpToDate with latest commits.
EDIT : Taking a public repo docker-jitsi-meet as a repo i need regular updates from and also modified and renamed in my private repo.
I have done the following :
1.I Bare cloned the public jitsi-meet repo to my local machine.
2.git clone --bare github.com/jitsi/docker-jitsi-meet.git.
3.cd into my local copy and git push github.com/user/project.git (private repo).
4 Deleted the bare copy and cloned the repo now git clone github.com/user/project.git
5.Add the public upstream repo as a remote: git remote add upstream github.com/jitsi/docker-jitsi-meet.git.
6 git fetch --all shows me lots of changes from upstream which i need to pull in.
I use
git merge upstream/master
and the following trace is displayed :
$ git merge upstream/master
Auto-merging CHANGELOG.md
Auto-merging docker-compose.yml
CONFLICT (content): Merge conflict in docker-compose.yml
Auto-merging focus/rootfs/defaults/jicofo.conf
CONFLICT (content): Merge conflict in focus/rootfs/defaults/jicofo.conf
CONFLICT (modify/delete): jibri/Dockerfile deleted in HEAD and modified in upstream/master. Version upstream/master of jibri/Dockerfile left in tree.
CONFLICT (modify/delete): prosody/rootfs/etc/cont-init.d/10-config deleted in HEAD and modified in upstream/master. Version upstream/master of prosody/rootfs/etc/cont-init.d/10-config left in tree.
Auto-merging web/rootfs/defaults/system-config.js
CONFLICT (content): Merge conflict in web/rootfs/defaults/system-config.js
Auto-merging xmpp/rootfs/defaults/conf.d/jitsi-meet.cfg.lua
CONFLICT (content): Merge conflict in xmpp/rootfs/defaults/conf.d/jitsi-meet.cfg.lua
Automatic merge failed; fix conflicts and then commit the result.
I did
git $ git merge upstream/master -X --strategy-option="find-renames=20"
and get the following :
error: Merging is not possible because you have unmerged files.
hint: Fix them up in the work tree, and then use 'git add/rm <file>'
hint: as appropriate to mark resolution and make a commit.
fatal: Exiting because of an unresolved conflict.
The simplest way is usually to add two remotes in your local clone and then continuously merge changes from the secondary remote. A remote is like a bookmark for another repository; when you clone, the origin remote is created automatically for you, which points to the source from which you cloned.
The following commands only need to be taken once:
git clone https://github.com/user/project.git localclone
cd localclone
git remote add upstream https://github.com/upstream/project.git
Then later to "sync" your fork:
git fetch --all
git merge upstream/master
git push origin HEAD
This will merge all changes that have happened in the "main" branch of the "upstream" remote/repository since you last fetched+merged.
Note that if commits in upstream change the same lines as you did in your fork, there will be merge conflicts which you need to resolve.

Make the current commit the only (initial) commit in a Git repository that was created with GitHub Desktop

I created my first GitHub repository using GitHub Desktop (Windows). It is a real mess with many revisions that are quite meaningless and some versions of files that I would rather were never uploaded. This was the result of a lot of experimenting to get the feel for how things would appear on GitHub. I want to get rid of all the history versions.
I am tempted to just copy my files on my drive to another folder then delete the repository folder from my drive. Also delete it from GitHub.
Then create a new repository with GitHub Desktop, perhaps with the same name or with a different name then rename it to the original. Could it be a simple as that or will GitHub still retain the files somewhere?
I haven't tried this because in my searching I keep finding all the complex steps to be performed to remove histories or remove files.
I sort of feel that what I am proposing is too simple.
Any opinions?
All of this got too confusing.
I just did what I said in the start of the thread.
It seems GitHub Desktop has some Username/Password problem and won't let me "Publish branch".
So I went to GitHub and created a new repository and uploaded all the files from my local folder.
It looks good to me.
There may be problems in the future. I guess I'll cross that bridge when (if) I come to it.
An alternative approach is to switch to command line and:
delete the .git folder in your repository
recreate it (git init .)
reset the origin remote: git remote add origin https://github.com//
Make a first commit with your current content:
git add .
git commit -m "first commit"
overwrite everything on the remote repo
git push --force -u origin master
The end result will be the same repo but with only one commit.
You can then switch back to GitHub Desktop.
From here.
First make sure you have Git for Windows installed, you are going to need to do git commands manually sooner or later.
Go to your local repository on your computer where your project is located. It's a good idea to show hidden files so you can see that you have the .git-folder and that the .gitignore-file is in place.
Go to the folder where the .git-folder is, right-click and click git bash here.
Now enter these commands:
Create Orphan Branch – Create a new orphan branch in git repository. The newly created branch will not show in ‘git branch’ command.
git checkout --orphan temp_branch
Add Files to Branch – Now add all files to newly created branch and commit them using following commands. Don't forget .gitignore!
git add .
git commit -m "the first commit"
Delete master Branch – Now you can delete the master branch from your git repository.
git branch -D master
Rename Current Branch – After deleting the master branch, let’s rename newly created branch name to master.
git branch -m master
Push Changes – You have completed the changes to your local git repository. Finally, push your changes to the remote (Github) repository forcefully.
git push -f origin master
Git overview

GitHub - Pull changes from a template repository

I have created a Template Repository in GitHub and then created some repositories based on the template. Since they were created, there have been updates to the template that I want to pull into those repositories.
Is this possible?
On the other repositories you have to add this template repository as a remote.
git remote add template [URL of the template repo]
Then run git fetch to update the changes
git fetch --all
Then is possible to merge another branch from the new remote to your current one.
git merge template/[branch to merge] --allow-unrelated-histories
https://help.github.com/en/articles/adding-a-remote
I will link to the same location as HRK44 but my answer is very different.
https://help.github.com/en/articles/creating-a-repository-from-a-template
Although forks and templates are mentioned in the same section, they are very different.
One of the differences mentioned in the link is:
A new fork includes the entire commit history of the parent repository, while a repository created from a template starts with a single commit.
This basicly means that you will not be able to pull new changes from the template as your git histories are very different and are not based on the same thing.
If you do use the method mentioned in the accepted answer, you will have very hard manual merges that will result in changes to all of the files received from the template, even if they werent changed since the first time you created that repo from that template.
In short, creating a repo from a template (using only master branch) is the same process as:
git clone template
cd folder
rm -rf .git
git init
git remote add origin <new repo url>
git add .
git commit -m "Initial Commit"
git push -u origin master
A few other things that are not (surprisingly) copied when creating a repo from a template:
(Unless github fix this at a later point)
Repo configurations (allowed merge types, permissions etc)
branch rules
So when using this at your organization, make sure to set all repo configurations on the newly created repo.
If you want to merge changes from a template into your project, you're going to need to fetch all of the missing commits from the template, and apply them to your own repo.
To do this, you're going to need to know the exact commit ID that you templated from, and you're going to need to know the commit ID of your first commit.
ORIGINAL_COMMIT_ID=<commit id from original repo you templated from>
YOUR_FIRST_COMMIT=<first commit id in your repo>
YOUR_BRANCH=master
Next you're going to need add the template as a remote, and fetch it.
git remote add upstream git#github.com:whatever/foo.git
git fetch upstream
And finally, you need to rebase all of the commits you're missing onto your branch
git rebase --onto ORIGINAL_COMMIT_ID YOUR_FIRST_COMMIT YOUR_BRANCH
What this is doing it basically creating a branch off of ORIGINAL_COMMIT_ID, then manually applying all of the commits on your original branch, onto this new branch.
This leaves you with what you would have had, if you had forked.
From here, you can git merge upstream/master just as if you had forked.
Once you've completed your merge, you'll need to use git push --force to push all of the changes up to the remote. If you're working with a team, you'll need to coordinate with everyone when doing this, as you're changing the history of the repo.
Note: It's important to note that this is only going to apply to one branch. If you have multiple feature branches, you'll need to perform the same steps to each one.
#daniel's answer also did not work for me because of the unrelated histories problem mentioned in #dima's answer. I achieved the desired functionality by doing the following:
Copy the URL for the template repository you wish to use to create a new repository. (ex: https://github.com/<username>/my-template.git)
Use GitHub Importer to make a new repository based on the template repository.
This solves the unrelated histories problem because it preserves the entire commit history of the template repository.
You need to use the Importer because you cannot fork your own repository. If you want to use someone else's template repository, you can just fork theirs.
Then, add the template repository as a remote.
git remote add template https://github.com/<username>/my-template.git
After you make new commits to the template repository, you can fetch those changes.
git fetch template
Then, merge or rebase. I recommend to merge on public repos and rebase on private repos.
To merge
git checkout <branch-to-merge-to>
git merge template/<branch-to-merge>
To rebase
git checkout <branch-to-merge-to>
git rebase upstream/<branch-to-merge>
NOTE: When rebasing, you must
git push origin <branch-name> --force
in order to override your old commits on your remote branch. This is why I recommend to rebase only on private repos.
I approached this differently as fetch & merge was not ideal as lot of files diverge across template and downstream projects. I only needed the common elements to sync.
lets says we have the below folder structure locally:
repos
├── template_repo
└── downstream_repo
1. Now create a git patch from the parent folder (repos):
git diff --no-index --diff-filter=d --output=upstream_changes.patch -- downstream_repo/some_common_path template_repo/some_common_path
NOTE - the order of the paths matters!, downstream_repo comes first! (interpret this as "what are the changes we need to make to downstream_repo to make it same as template_repo"; look at the --name-status output, it will hopefully make sense.)
--no-index option generates git diff based on filesystem paths. Path can be a single file or a folder.
--diff-filter=d will ignore any files that are in the downstream_repo but not in the template_repo. This only applies when diffing folder paths.
You can use --stat, --name-status to see what the patch will contain.
Review the generated patch.
2. Change to downstream_repo folder and apply the patch
git apply -p2 ../upstream_changes.patch
explanation for -p<n> option from the official doc:
Remove leading path components (separated by slashes) from
traditional diff paths. E.g., with -p2, a patch against a/dir/file
will be applied directly to file. The default is 1.
Using -p2 will drop a/downstream_repo and b/template_repo from the diff paths allowing the patch to apply.
This is the reason for starting with above illustrated folder structure.
Once the patch is applied, rest of the process should be familiar.
All of these options are clearly explained in git diff and git apply official docs.
Another option is to create a patch from the necessary commits and move the patch to a new project
git format-patch -1 HEAD
Insert a patch
git am < file.patch
details are here
I ran into this same issue. I have 10+ projects all created from the same template project (react-kindling) and using git alone wasn't sufficient, as it would pull in changes to the template that I didn't want in my child projects.
I ended up creating an npm utility for updating child projects from template starter projects. You can check it out here:
LockBlocks
It's been a real life saver. Pulling changes from the template is a heck of a lot easier now.
This works too:
git remote add template git#github.com:org/template-repo.git
git fetch --all
git merge template/main --allow-unrelated-histories

Keeping a collection of mercuial subrepos at tip

I would like to keep a collection of mercurial subprepositories updates at tip and this is what I've come up with. Are there any gotchas I'm not seeing if I do it this way?
Backstory
For many years now I have been using monolithic subversion repository main but I am getting ready to convert it over to mercurial. The only thing I don't like about mercurial is that I can't clone just one subdirectory. I was thinking of making each top level directory of main into its own mercurial repository. Then I could create one mercurial repo called maincollections that would reference each new mercurial repo as a subrepo. In order to get changes to any subrepo by just pulling once inside maincollections I set up the following.
Method
When a push is received on the server in any one of the subrepos it triggers the changegroup hook commit-sub to force an update and commit of .hgsubstate in the maincollections repo.
commit-subs
#!/bin/bash
SUBNAME=$(basename $(pwd))
cd ../../maincollection/$SUBNAME
hg pull
hg up
cd ..
hg ci -m "Automated update of .hgsubstate"
Directory organization
maincollection # repo with subrepos
main/* # Individual subrepos

Is 'pull' a synonym for 'clone' in a Mercurial source-control repository?

I'm seeing the command 'pull' and wondering how that's different from a 'clone'. Both terms seem to imply retrieving code from some remote repository. Is there some subtle distinction here?
Use clone when you need to make a new repository based on another. Use pull later to transfer new changesets into the clone. You cannot use clone to fetch just the newest changesets — that is what pull is for. The pull command will compare the two repositories, find the missing changesets in your repository and finally transfer those.
However, you are right that there are similarities between clone and pull: they both transfer history between repositories. If you clone first
hg clone https://www.mercurial-scm.org/repo/hg/
then this has the exact same effect as doing
hg init hg
cd hg
hg pull https://www.mercurial-scm.org/repo/hg/
hg update
You get the exact same history in both cases. The clone command is more convenient, though, since it also edits the .hg/hgrc file for you to setup the default path:
[paths]
default = https://www.mercurial-scm.org/repo/hg/
This is what lets you do hg pull in the repository without specifying a URL. Another advantage of using clone is when you work with repositories on the same disk: hg clone a b will be very fast and cheap in terms of disk space since b will share the history with a. This is done using hardlinks and works on all platforms (Windows, Linux, Mac).
hg clone is how you make a local copy of a remote repository. The Subversion equivalent is svn checkout.
hg pull pulls changes from another repository. hg update applies those changes to the local repository. hg pull -u is equivalent to hg pull; hg update. The Subversion equivalent to hg pull -u is svn update.
clone creates a new repository as a copy of an existing repository.
pull imports all changesets (not already present) from another repository into an existing repository.