Repository: getnikola/nikola

Issue:
github_deploy should commit to the source branch automatically
I am using the xxx.github.io repo on github, so i set the GITHUB_SOURCE_BRANCH ='source', and GITHUB_DEPLOY_BRANCH='master". and the OUTPUT_FOLDER is default.
so, basically the source branch has folder structure like this:

source
├── README.txt
├── **pycache**
├── cache
├── conf.py
├── files
├── galleries
├── images
├── listings
├── output
├── plugins
├── posts
├── stories
└── templates

and then i run `nikola github_deploy`, i have generated a mater branch which contains the output results, it is folder structure is like below:

master
├── 2015
├── **pycache**
├── archive.html
├── assets
├── authors
├── cache
├── categories
├── favicon.ico
├── galleries
├── images
├── index.html
├── listings
├── output
├── posts
├── robots.txt
├── rss.xml
├── sitemap.xml
├── sitemapindex.xml
├── stories
└── zh_cn

everything works fine, but i have another output folder in this master branch, which contains exactly the same content as its parent folder... am i doing something wrong? or it suppose to be like this?
if so, i think it is more reasonable to just remove this output folder (and the cache folders as well).

ps: everything on github.com is fine, there is no output folder or cache folders in the master branch, so locally if you run `git status` you have:

```
  Untracked files:
  (use "git add <file>..." to include in what will be committed)
.doit.db.db
__pycache__/
cache/
output/
posts/test.rst
```



Discussion:
I think you need to add some things to .gitignore on your source branch, namely

```
cache
*.py[co]
.doit.db
output
```

You might also want to put it in files/ so it gets copied to master.

(why does `.doit.db.db` exist?)

`output` is already in the .gitignore list.
Through a quick review of the source code, i think when run 'nikola github_deploy', it pushes the contents in the output folder to the github repo directly, i don't see where the local master branch is generated.

I did an experiment by cloning only the source branch to a local folder/repo, and run `nikola build`, it then adds the mater branch to the local repo, and that master branch has the output folder, while there is no output folder in the github master branch, 

another thing i would suggest is that when run `nikola github_deploy` it may be nice to commit and push the source branch to github as well. currently you have to do it manually

We use ghp-import, which does all the branching. About committing, not everyone might want this, but we could make it a setting one day.

I’ll try to get this done this week.


Resolving patch:
diff --git a/nikola/nikola.py b/nikola/nikola.py
--- a/nikola/nikola.py
+++ b/nikola/nikola.py
@@ -512,6 +512,7 @@ def __init__(self, **config):
             'GITHUB_SOURCE_BRANCH': 'master',
             'GITHUB_DEPLOY_BRANCH': 'gh-pages',
             'GITHUB_REMOTE_NAME': 'origin',
+            'GITHUB_COMMIT_SOURCE': False,  # WARNING: conf.py.in overrides this with True for backwards compatibility
         }
 
         # set global_context for template rendering
diff --git a/nikola/plugins/command/github_deploy.py b/nikola/plugins/command/github_deploy.py
--- a/nikola/plugins/command/github_deploy.py
+++ b/nikola/plugins/command/github_deploy.py
@@ -97,30 +97,61 @@ def _execute(self, command, args):
 
         return
 
-    def _commit_and_push(self):
-        """Commit all the files and push."""
-        source = self.site.config['GITHUB_SOURCE_BRANCH']
-        deploy = self.site.config['GITHUB_DEPLOY_BRANCH']
-        remote = self.site.config['GITHUB_REMOTE_NAME']
-        source_commit = uni_check_output(['git', 'rev-parse', source])
-        commit_message = (
-            'Nikola auto commit.\n\n'
-            'Source commit: %s'
-            'Nikola version: %s' % (source_commit, __version__)
-        )
-        output_folder = self.site.config['OUTPUT_FOLDER']
-
-        command = ['ghp-import', '-n', '-m', commit_message, '-p', '-r', remote, '-b', deploy, output_folder]
-
+    def _run_command(self, command, xfail=False):
+        """Run a command that may or may not fail."""
         self.logger.info("==> {0}".format(command))
         try:
             subprocess.check_call(command)
+            return 0
         except subprocess.CalledProcessError as e:
+            if xfail:
+                return e.returncode
             self.logger.error(
                 'Failed GitHub deployment — command {0} '
                 'returned {1}'.format(e.cmd, e.returncode)
             )
-            return e.returncode
+            raise SystemError(e.returncode)
+
+    def _commit_and_push(self):
+        """Commit all the files and push."""
+        source = self.site.config['GITHUB_SOURCE_BRANCH']
+        deploy = self.site.config['GITHUB_DEPLOY_BRANCH']
+        remote = self.site.config['GITHUB_REMOTE_NAME']
+        autocommit = self.site.config['GITHUB_COMMIT_SOURCE']
+
+        try:
+            if autocommit:
+                commit_message = (
+                    'Nikola auto commit.\n\n'
+                    'Nikola version: {0}'.format(__version__)
+                )
+                e = self._run_command(['git', 'checkout', source], True)
+                if e != 0:
+                    self._run_command(['git', 'checkout', '-b', source])
+                self._run_command(['git', 'add', '.'])
+                # Figure out if there is anything to commit
+                e = self._run_command(['git', 'diff-index', '--quiet', 'HEAD'], True)
+                if e != 0:
+                    self._run_command(['git', 'commit', '-am', commit_message])
+                else:
+                    self.logger.notice('Nothing to commit to source branch.')
+
+            source_commit = uni_check_output(['git', 'rev-parse', source])
+            commit_message = (
+                'Nikola auto commit.\n\n'
+                'Source commit: {0}'
+                'Nikola version: {1}'.format(source_commit, __version__)
+            )
+            output_folder = self.site.config['OUTPUT_FOLDER']
+
+            command = ['ghp-import', '-n', '-m', commit_message, '-p', '-r', remote, '-b', deploy, output_folder]
+
+            self._run_command(command)
+
+            if autocommit:
+                self._run_command(['git', 'push', '-u', remote, source])
+        except SystemError as e:
+            return e.args[0]
 
         self.logger.info("Successful deployment")
 


Test patch: