0

I've seen many variants of this question on SO but none of them had what I looking for. Say I have a repo ~/MyRepo/:

$ ls -a ~/MyRepo
code.r junk.txt .git

In MyRepo only the file code.r is being tracked, and junk.txt is not tracked. And say I have a remote (e.g. on Dropbox) at ~/Dropbox/MyShare/ that a friend has access to (only for reading). The intent is for this remote to only contain my latest committed version of code.r, and not contain junk.txt. I'm trying to achieve the following: whenever I commit code.r I want to be able to update (automatically if possible) the remote ~/Dropbox/MyShare/code.r with the committed version of ~/MyRepo/code.r.

I am aware of .gitignore but not interested in that route because I have several untracked files that I want to ignore, and I only want to "push" the files I'm tracking to the remote. I also tried the approach of doing a cloning into ~/Dropbox/MyShare/ but cloning or pulling always seem to include tracked and untracked files, thus polluting my Remote.

My current solution is to have a post-commit hook under ~/MyRepo/.git/hooks/ that has explicit commands to individually copy all the "files I care about" to the remote. I don't like this solution because the "files I care about" can change, and I don't have to go and update the post-commit hook.

I am hoping there is a way to automatically make the last-committed versions available in ~/Dropbox/MyShare/ by some combination of git commands. I don't mind doing a single manual "push" command every time I commit in ~/MyRepo/.

Here is what I tried based on one of the answers below, but I am still stumped.

# create my repo
mkdir foo
cd foo
git init
touch fileA fileB fileC
git add fileA
git commit -m 'new'

# now create remote 
mkdir ../foo_remote
cd ../foo_remote
git init
cd ../foo
git remote add foo_remote ../foo_remote

bash-3.2$ git remote -v                                                                                                                                                                                                                                                         
foo_remote      ../foo_remote (fetch)                                                                                                                                                                                                                                           
foo_remote      ../foo_remote (push)                                                                                                                                                                                                                                            

Now when I try to push, I get this mean error message:

bash-3.2$ git push foo_remote master                                                                                                                                                                                                                                            

Counting objects: 3, done.                                                                                                                                                                                                                                                      
Writing objects: 100% (3/3), 207 bytes, done.                                                                                                                                                                                                                                   
Total 3 (delta 0), reused 0 (delta 0)                                                                                                                                                                                                                                           
Unpacking objects: 100% (3/3), done.                                                                                                                                                                                                                                            
remote: error: refusing to update checked out branch: refs/heads/master                                                                                                                                                                                                         
remote: error: By default, updating the current branch in a non-bare repository                                                                                                                                                                                                 
remote: error: is denied, because it will make the index and work tree inconsistent                                                                                                                                                                                             
remote: error: with what you pushed, and will require 'git reset --hard' to match                                                                                                                                                                                               
remote: error: the work tree to HEAD.                                                                                                                                                                                                                                           
remote: error:                                                                                                                                                                                                                                                                  
remote: error: You can set 'receive.denyCurrentBranch' configuration variable to                                                                                                                                                                                                
remote: error: 'ignore' or 'warn' in the remote repository to allow pushing into                                                                                                                                                                                                
remote: error: its current branch; however, this is not recommended unless you                                                                                                                                                                                                  
remote: error: arranged to update its work tree to match what you pushed in some                                                                                                                                                                                                
remote: error: other way.                                                                                                                                                                                                                                                       
remote: error:                                                                                                                                                                                                                                                                  
remote: error: To squelch this message and still keep the default behaviour, set                                                                                                                                                                                                
remote: error: 'receive.denyCurrentBranch' configuration variable to 'refuse'.                                                                                                                                                                                                  
To ../foo_remote                                                                                                                                                                                                                                                                
 ! [remote rejected] master -> master (branch is currently checked out)                                                                                                                                                                                                         
error: failed to push some refs to '../foo_remote'           

Any ideas where I'm going wrong?

Michael Durrant
  • 93,410
  • 97
  • 333
  • 497
Prasad Chalasani
  • 19,912
  • 7
  • 51
  • 73

2 Answers2

4

If you do not add the file why would it be pushed to the remote - simple answer do not add files to you local repo you do not want pushed.

Either put the files in the repo or do not - the point of a DVCS is to have the same files everywhere.

I would look again at .gitignore it works - you can keep it locally and not include it in the repo if you do not want to share it - this is the sole purpose of this file and the fact you do not want to use it seems odd. Bit like saying I want to compile C files but I do not want to use a compiler

mkdir foo
cd foo
git init
touch fileA fileB fileC fileD
git add fileA
git commit -m "New file"
git push

Only fileA will get pushed

Adrian Cornish
  • 23,227
  • 13
  • 61
  • 77
  • Maybe I'm missing something basic -- I couldn't figure out a way of creating a remote clone that only contains my *tracked* files -- every approach I tried always copied over the untracked files as well. If there was a way of creating a remote that has *only* my tracked files, than I'd be done, since like you said, a push would only send committed files. – Prasad Chalasani Sep 22 '12 at 02:11
  • 1
    Right - do not do `git add .` because that adds all untracked files - add the files you want – Adrian Cornish Sep 22 '12 at 02:12
  • Makes sense, but I guess I'm not clear on how exactly to the create the remote repo in the right way -- I elaborated my question based on your suggestion, and I get an error when I try to push. – Prasad Chalasani Sep 22 '12 at 02:28
  • 1
    When you create the remote use `git --bare init` – Adrian Cornish Sep 22 '12 at 02:30
  • I should add a reason when you do `git init` you create a repository for use - using the --bare tag means that it is not a normal for work repo. Say you and I shared a repo the last thing I want is you pushing changes to my repo that break things - when you say --bare your are indicating it is not used by a developer but is jut a repo copy that is not used by a person – Adrian Cornish Sep 22 '12 at 02:33
  • Ah but that's one of the things I tried -- doing the --bare-init creates a ".git"-like directory that contains git-tracking files/directories, but will not contain the actual working files. I need the remote to contain my working files. I tried another idea where I first clone the local to the remote, but when I clone, it copies *all* my files, including untracked ones! – Prasad Chalasani Sep 22 '12 at 02:33
  • Why do you need working file? Anyone can clone from the bare repo? – Adrian Cornish Sep 22 '12 at 02:34
  • Well the intent is that the remote is really just a directory where I want my committed files to be copied to -- it's intended to be picked up (read-only) by anyone without having to use git commands. – Prasad Chalasani Sep 22 '12 at 02:36
  • 1
    Do it the other way round - from the supposed remote - do a `git pull` and make your repo the remote – Adrian Cornish Sep 22 '12 at 02:39
  • Actually your comment above gave me an idea -- anyone can clone from the bare repo, so all I need to do is to have a post-receive hook under the bare-init remote repo that clones itself to the actual final remote repo. That seems to work, thanks. – Prasad Chalasani Sep 22 '12 at 02:42
  • I put in a post-receive hook under the bare repo that cloned itself to the "final working" repo -- worked fine the first time, but when I pushed again to the bare-repo, the hook caused an error because the clone command complained that the repo already exists... – Prasad Chalasani Sep 22 '12 at 03:03
  • Need more info - what was in the hook? – Adrian Cornish Sep 22 '12 at 03:07
  • I meant the contents of the bash script in the hook – Adrian Cornish Sep 22 '12 at 03:13
  • yes that's what I have in the post-receive hook -- `#!/bin/sh` on one line, then `git clone . ~/path/to/foo_working_remote` -- this worked fine the first time but failed on later pushes with the error because the foo_working_remote already exists. – Prasad Chalasani Sep 22 '12 at 03:22
  • This does not make sense for the git workflow - I think I am misunderstanding what you need - maybe a new StackOverflow question with better requirement of what you need – Adrian Cornish Sep 22 '12 at 03:31
  • Thanks for the tips Adrian -- I think my problem is that somehow my Repo (which *was* indeed on Dropbox!) got into a state where, when I clone it to another fresh repo, it was copying ALL files, including untracked ones. That was the source of my problems. I nuked the .git dir in my main repo, and "git added" only the "files I care about". Now when I clone it, it correctly copied only the added/tracked files, leaving out the rest of the junk. Now I'm in good shape, I can use a post-commit hook in my main Repo that just goes to the remote dir, and does a "git pull" to refresh contents. – Prasad Chalasani Sep 22 '12 at 18:18
  • 1
    Although strictly speaking there was no "right answer" to this, I'll accept yours since you "worked harder" :) – Prasad Chalasani Sep 22 '12 at 18:21
3

This doesn't directly answer your question but it's also a bit long for a comment and I wanted to share it anyway. It may help some from going through the pain I felt.

So my advice from experience is:

Don't mix Dropbox and github repositories.

I got burned a couple of times with this with conflicts for nearly every file getting generated.

I now always keep my github (i.e. rails) projects in a different folder.

I create ~/Dropnot as the name for this different folder.
As always I create an alias in my .bash_aliases file, in this case alias not='cd ~/Dropnot'

When I am setting up a new machine however, I often use a Dropbox/xfer folder to quickly do a 1 time setup to transfer all my Dropnot files (I copy them there on another machine just for that).
Going forward I then use fetch/pull/push for changes to the various repos under that directory.

Michael Durrant
  • 93,410
  • 97
  • 333
  • 497
  • Thanks Michael -- (please see my last comment below) -- somehow it looks like my main Repo got into a state where cloning it copied ALL files, including un-tracked ones. I don't know if that's related to it being under Dropbox or not, but when I nuked the .git dir and did a "git add" on only the files I care about, and then cloned it, it now correctly copies over only the tracked files. – Prasad Chalasani Sep 22 '12 at 18:20
  • Sure. Just remember that if you made a change using github via a pull and then go to another machine that has your dropbox it will see them as changed files and create new ones. This continually led to conflict for me but may only be seen if you use multiple machines. – Michael Durrant Sep 22 '12 at 20:20