Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I keep two git repositories in sync?

Tags:

git

Here is the scenario. I have two machines, "desktop" and "laptop".

On desktop I do:

mkdir git_test
cd git_test
git init
dd if=/dev/urandom of=test.img bs=1k count=1000
git add test.img
git commit -m "Added first image"

Then on laptop I do:

git clone [USER]@desktop:/home/[USER]/git_test    
cd git_test
dd if=/dev/urandom of=test2.img bs=1k count=1000
git add test2.img
git commit -m "Added second image"

Then I want the git repo on my desktop to look like the git repo on my laptop. On the laptop, I issue the following: git push origin master

But then I get:

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'.

How do I keep these two repos in sync?

The error messages seem to imply that git has the functionality that I desire, but for some reason it seems to be a more advanced workflow. I heard someone say once that you can't push to the branch you are currently on, can someone elaborate on that as a possible solution? I would have no problem with a solution of that nature, ie, I could work on a certain branch on my laptop, and a different branch on my desktop, and then just sync those up somehow so they are identical.

Please note the following!

  • I do not want to use a centralized repo, like github, for several reasons. The first is security. The second is simplicity. The third is that due to circumstances I won't go into here, I can't count on having an internet connection to some remote server, I just have my two machines connected via LAN. Finally, I want to learn how to do things the way I requested here, as to gain that specific piece of knowledge.

  • I also do not want to use a bare repo, as a bare repo has a bunch of cruft in the root dir. This is ugly and messy. The whole reason I moved to git from subversion is that git looked like a much cleaner, decentralized solution. Also, I have some somewhat non-technical people that will be operating in the root dir of the desktop, they will get quite confused by the cruft. The beauty of git is (I thought) that everything hides in .git folders. Edit: Apparently I wasn't clear enough with this point. Imagine I have a "Documents" folder with the following sub folders: mydata1 and mydata2. This isn't a contrived example, this is exactly the issue I am trying to deal with. mydata1 should contain "test.img" and that file only, but instead it now has:

    branches config description HEAD hooks info objects refs

I wanted to be able to just cd into mydata1 and start editing files, but instead I have to try and cd through branches, or whatever even just to get work done. And to have this sort of directory structure for every subfolder that was in "documents" is just unworkable. Please, please don't tell me to do things this way. Please just answer the question. Thanks.

These two points are the entire reason I am posting this question here. Please only reply if you have an answer to this question. :) Thanks!!

like image 497
cat pants Avatar asked Jan 17 '13 01:01

cat pants


People also ask

Can I have multiple git repositories in one folder?

Yes, it is possible to have two git repositories in one directory. I'm assuming that one remote repository is in GitHub and the other in GitLab. I'm also using two different SSH keys to connect to these remote repositories.


3 Answers

One way of doing this is to pull, not push. After you've set up your two machines, on the first machine:

git remote add origin [USER]@laptop:/home/[USER]/git_test
git pull # Complains about untracked branch while adding the branch you want to track
git branch --set-upstream master origin/master
git pull

Now you can pull commits from either machine. If you wanted to push, I'm not sure how to go about that with a decentralized setup.

like image 63
cjc343 Avatar answered Oct 16 '22 04:10

cjc343


I recently had an issue where my server and desktop got out of sync. After searching around the web for a while I wasn't able to find an answer that dealt with my exact situation. So I called Rackspace support and they were able to provide me with what I think is a better answer than I was able to find online.

This particular thread was the closest to my issue so I thought I would share how I solved the problem on here in case anyone encounters the same issue in the future.

Here's what went wrong

I was trying to install the Sweet Tooth plugin for Magento and followed along with the usual steps we all go through to install Magento extensions. This means taking a bunch of files and putting them in my App, JS, and Skin directories.

In the app/design/adminhtml directory there is a "base" folder. If you know anything about Magento then you know they have a zillion warnings about messing with the base files. In short - don't do it.

I assumed that since my local repo didn't have the "base" directory I'd be a-okay putting it on my local machine. Unfortunately and much to my dismay, this meant that when I did my add it added a "base" directory with only the files for Sweet Tooth. When I then put this on the server it wiped-out my entire base directory and Boom! down went Magento.

Luckily I was able to get back to the previous server state by using the following life-saving command:

git reset --hard HEAD@{1}

This command takes you back to the previous commit and instantly everything was back to normal. Of course now my server and desktop were out of sync since my server was now one commit behind.

To add insult to injury I made a very stupid mistake and deleted the files for the extension from my computer and did another commit on my desktop so now the server and desktop were out of sync by two commits and git now has these files in its cache.

Here's how I solved it

Obviously this leaves you in a pretty annoying place because doing a git pull on my server will wipe-out my "base" directory every single time. Also since it's two commits ahead I can't just rollback one commit.

I called Rackspace who at this point are Gods in my mind and found two different ways to solve this depending on whether you want to do this from the server-side or the desktop-side.

As it turns-out you really can't do this from the server-side since the files are now no longer on the desktop. While they recommended doing a git commit -a and then doing a push from the server followed by a pull from the desktop this just won't work, the files aren't on the desktop any more.

So you have to fix it from the Desktop and you need to get those darn files out of the cache.

Fixing Sync Issue From The Desktop

To get the files out of the cache I issued the following command over, and over, and over again until the files that I had removed were also removed according to git.

git rm -r --cached /folder/directory for directories

and

git rm --cached /folder/file for files

Now that this was out of the cache I was able to do a commit and finally let git know these files were actually gone.

This was followed by a push to the master. Then all that was left to do was a pull from the server and viola, back in business!

** Conclusion and Lessons Learned **

The lessons learned here were some big ones and I'm writing this post for other programmers that have a similar issue as well as myself to remind me of what not to do ever again.

  1. If you don't have a folder in your local repo that is on the server, don't add it to your local repo with only a few files in it, this will zero-out the directory on the server.

  2. If you do accidentally screw things up, make sure to remove the files with git, don't delete them from your local filesystem

  3. git rest --hard HEAD@{1} can be your best friend sometimes

I hope this helps anyone else that is in a similar situation. I spent hours pouring through docs online but couldn't find anything with the complexities that I ran-into here so if I can help someone else save some time and get a few less grey hairs then my nightmare will have served some good for the world!

like image 2
Morgan Linton Avatar answered Oct 16 '22 04:10

Morgan Linton


I may be missing why you don't want to use a bare repo, and I believe the pull only solution should work fine, but I also believe the "cruft" can still be hidden in the way you desire when working with a bare repo.

On your desktop, if you:

mkdir git_test
git init --bare git_test

And then:

git clone bare_repo_directory new_location

You can push and pull normally to the bare repo (referencing it as origin by default) from the clone, and no one will have to deal with the extra content it contains; the clones will only have the .git directory.

To push you'll need to run:

git push origin master (assuming you're working out of master)

For your laptop:

git clone [USER]@desktop:path_to_bare

And work should be normal in the cloned copy. You'll push and pull from origin (which is the bare repo), but you shouldn't need to work in it directly.

like image 1
Myles Avatar answered Oct 16 '22 04:10

Myles