2014-04-19 101 views
6

我正在尋找一些援助,請使用Emacs/Magit將本地存儲庫更改推送到遠程網站和Github一舉。Emacs - 如何將Git存儲庫推送到多個遙控器

我發現了一個非Emacs /非Magit相關線程(https://stackoverflow.com/a/3195446/2112489),其中有評論指出它是推送到遠程和Github的權威答案,並且它有幾百個大拇指。我假設(也許不正確)這是我的計算機上的$HOME目錄中的本地.gitconfig文件的一個很好的起點。

[remote "GitHub"] 
    url = [email protected]:elliottcable/Paws.o.git 
    fetch = +refs/heads/*:refs/remotes/GitHub/* 
[branch "Master"] 
    remote = GitHub 
    merge = refs/heads/Master 
[remote "Codaset"] 
    url = [email protected]:elliottcable/paws-o.git 
    fetch = +refs/heads/*:refs/remotes/Codaset/* 
[remote "Paws"] 
    url = [email protected]:Paws/Paws.o.git 
    fetch = +refs/heads/*:refs/remotes/Paws/* 

在Emacs/Magit基本按命令只推一次一個:

C-u P P [and then use arrow keys to select from the choices in the minibuffer] RET 

查看可用命令的Magit的cheatsheet:http://daemianmack.com/magit-cheatsheet.html


初步思考 - 使用/usr/local/git/bin/git remote -v獲取已配置的遙控器列表,然後使用結果推送到每一個。 。 。可行,但複雜。

$ MP:my_project.git HOME$ /usr/local/git/bin/git remote -v 

    origin [email protected]:lawlist/my_project.git (fetch) 
    origin [email protected]:lawlist/my_project.git (push) 
    remote_website [email protected]:my_project.git (fetch) 
    remote_website [email protected]:my_project.git (push) 

命令行RECIPE - 分別推到遠程和Github上:

;; Setup the remote repository and the hook; and the remote destination folder. 
ssh [email protected] 
mkdir /home/lawlist/my_project.git 
cd my_project.git 
git init --bare 
;; git update-server-info # If planning to serve via HTTP 
cat > /home/lawlist/my_project.git/hooks/post-receive ;; RET 
#!/bin/sh ;; RET 
GIT_WORK_TREE=/home/lawlist/my_project git checkout -f ;; RET 
;; C-d 
chmod 755 /home/lawlist/my_project.git/hooks/post-receive 
mkdir /home/lawlist/my_project 
exit 

;; On local machine. 
mkdir /Users/HOME/.0.data/.0.emacs/elpa/my_project.git 
touch /Users/HOME/.0.data/.0.emacs/elpa/my_project.git/README.md 
cd /Users/HOME/.0.data/.0.emacs/elpa/my_project.git 
/usr/local/git/bin/git init 
/usr/local/git/bin/git add . 
/usr/local/git/bin/git commit -m "First commit." 
curl -u lawlist:12345678 https://api.github.com/user/repos -d '{"name":"my_project.git"}' 
/usr/local/git/bin/git remote add origin [email protected]:lawlist/my_project.git 
/usr/local/git/bin/git remote add remote_website [email protected]:my_project.git 
/usr/local/git/bin/git push origin master 
/usr/local/git/bin/git push remote_website master 

;; For modification of local files 
/usr/local/git/bin/git add . 
/usr/local/git/bin/git commit -m "This is a modification . . . ." 
/usr/local/git/bin/git push origin master 
/usr/local/git/bin/git push remote_website master 
+1

+1感謝分享! – itsjeyd

回答

4

EDIT(2014年4月23日):添加了非Magit溶液階段全部,全部提交(使用默認提交消息),並推送到所有遙控器。

編輯(2014年4月24日):所有進程的打印輸出現在被髮送到git-status-buffer,這是顯示在函數的末尾 - 與選項的用戶選擇如何處理做窗口 - 例如,刪除窗口,刪除緩衝區和窗口,或者什麼都不做。 (propertize "[...]" 'face 'font-lock-warning-face)增加了一些漂亮的色彩。依賴於預先安裝的Magit的函數的初稿已經被移到了這個答案的底部 - 該函數可以工作,但並不像當前版本那樣複雜,不依賴於安裝Magit。

(defvar git-status-buffer "*GIT-STATUS*" 
    "The buffer name of the git-status-buffer.") 

(defvar git-branch-name nil 
"The current branch of the working Git directory.") 
(make-variable-buffer-local 'git-branch-name) 

(defvar git-remote-list nil 
"List of remote locations -- e.g., lawlist_remote or github_remote.") 
(make-variable-buffer-local 'git-remote-list) 

(defvar git-commit-message (format "Committed -- %s" (current-time-string)) 
"The predetermined Git commit message.") 
(make-variable-buffer-local 'git-commit-message) 

(defun git-branch-process-filter (proc string) 
    (with-current-buffer (get-buffer git-status-buffer) 
    (set (make-local-variable 'git-branch-name) 
     (car (split-string string "\n"))))) 

(defun git-push-process-filter (proc string) 
    (when (string-match "password" string) 
    (process-send-string 
     proc 
     (concat (read-passwd "Password: ") "\n"))) 
    (when (and 
     (not (string-equal "Password: " string)) 
     (not (string-equal "\n" string)) 
     (not (string-equal "stdin: is not a tty\n" string))) 
    (with-current-buffer git-status-buffer 
     (goto-char (point-max)) 
     (insert "\n" (replace-regexp-in-string "\^M" "\n" string))))) 

(defun git-push-process-sentinel (proc string) 
    (when (= 0 (process-exit-status proc)) 
    (with-current-buffer (get-buffer git-status-buffer) 
     (insert 
     "\n" 
     (propertize 
      (format "Process `%s` has finished pushing to `%s`." proc git-remote-name) 
      'face 'font-lock-warning-face) 
     "\n")) 
    (throw 'exit nil))) 

(defun stage-commit-push-all() 
"This function does the following: 
    * Save the current working buffer if it has been modified. 
    * Obtain the name of the selected branch in the current working buffer. 
    * Gather a list of all remotes associated with working directory Git project. 
    * Stage all -- `/usr/local/git/bin/git add .` 
    * Commit all -- `/usr/local/git/bin/git commit -m [git-commit-message]` 
    * Push to all remotes: `/usr/local/git/bin/git push -v [remote] [current-branch]`" 
(interactive) 
    (when (buffer-modified-p) 
    (save-buffer)) 
    (when (get-buffer git-status-buffer) 
    (with-current-buffer (get-buffer git-status-buffer) 
     (kill-local-variable 'git-remote-list) 
     (kill-local-variable 'git-branch-name) 
     (erase-buffer))) 
    (start-process 
    "current-branch" 
    git-status-buffer 
    "/usr/local/git/bin/git" 
    "rev-parse" 
    "--abbrev-ref" 
    "HEAD") 
    (set-process-filter (get-process "current-branch") 'git-branch-process-filter) 
    (set-process-sentinel 
    (get-process "current-branch") 
    (lambda (p e) (when (= 0 (process-exit-status p)) 
     (set-process-sentinel 
     (start-process 
      "list-remotes" 
      git-status-buffer 
      "/usr/local/git/bin/git" 
      "remote" 
      "-v") 
     (lambda (p e) (when (= 0 (process-exit-status p)) 
      (let* (
       beg 
       end 
       git-remote-name) 
      (with-current-buffer (get-buffer git-status-buffer) 
       (goto-char (point-max)) 
       (while (re-search-backward "\(push\)" nil t) 
       (beginning-of-line 1) 
       (setq beg (point)) 
       (re-search-forward "\t" nil t) 
       (setq end (- (point) 1)) 
       (setq git-remote-name (buffer-substring-no-properties beg end)) 
       (setq git-remote-list 
        (append (cons git-remote-name git-remote-list)))))) 
      (set-process-sentinel 
      (start-process 
       "stage-all" 
       git-status-buffer 
       "/usr/local/git/bin/git" 
       "add" 
       ".") 
      (lambda (p e) (when (= 0 (process-exit-status p)) 
       (with-current-buffer (get-buffer git-status-buffer) 
       (goto-char (point-max)) 
       (insert "\n")) 
       (set-process-sentinel 
       (start-process 
        "commit-all" 
        git-status-buffer 
        "/usr/local/git/bin/git" 
        "commit" 
        "-m" 
        git-commit-message) 
       (lambda (p e) (when (= 0 (process-exit-status p)) 
        (mapcar (lambda (git-remote-name) 
        (let ((proc 
         (start-process 
          "push-process" 
          git-status-buffer 
          "/usr/local/git/bin/git" 
          "push" 
          "-v" 
          (format "%s" git-remote-name) 
          (format "%s" 
          (with-current-buffer (get-buffer git-status-buffer) 
           git-branch-name))))) 
         (set-process-filter proc 'git-push-process-filter) 
         (set-process-sentinel proc 'git-push-process-sentinel) 
         (recursive-edit))) 
        (with-current-buffer (get-buffer git-status-buffer) 
         git-remote-list)) 
        (display-buffer (get-buffer git-status-buffer)) 
        (message (concat 
        git-status-buffer 
        " -- [" 
        (propertize "d" 'face 'font-lock-warning-face) 
        "]elete window | [" 
        (propertize "k" 'face 'font-lock-warning-face) 
        "]ill buffer + delete window | [" 
        (propertize "n" 'face 'font-lock-warning-face) 
        "]othing")) 
        (let* (
         (git-window-options (read-char-exclusive)) 
         (target-window (get-buffer-window git-status-buffer))) 
        (cond 
         ((eq git-window-options ?d) 
         (with-current-buffer (get-buffer git-status-buffer) 
          (delete-window target-window))) 
         ((eq git-window-options ?k) 
         (with-current-buffer (get-buffer git-status-buffer) 
          (delete-window target-window) 
          (kill-buffer (get-buffer git-status-buffer)))) 
         ((eq git-window-options ?n) 
         (message "Done!")) 
         (t (message "You have exited the sub-function.")))) 
       ))))))))))))) 

初稿(2014年4月19日):該函數需要Magit的預先存在的安裝。代碼以上確實不是要求安裝Magit。

(defun push-to-all-remotes() 
"This function requires a pre-existing installation of Magit, and the function assumes 
that the user has already staged and committed -- i.e., it only pushes to all remotes." 
(interactive) 
    (let* (beg end remote) 
    (when (get-buffer "*REMOTES*") 
     (with-current-buffer (get-buffer "*REMOTES*") 
     (erase-buffer))) 
    (set-process-sentinel 
     (start-process 
     "list-remotes" 
     "*REMOTES*" 
     "/usr/local/git/bin/git" 
     "remote" 
     "-v") 
     (lambda (p e) (when (= 0 (process-exit-status p)) 
     (with-current-buffer (get-buffer "*REMOTES*") 
      (goto-char (point-max)) 
      (while (re-search-backward "\(push\)" nil t) 
      (beginning-of-line 1) 
      (setq beg (point)) 
      (re-search-forward "\t" nil t) 
      (setq end (- (point) 1)) 
      (setq remote (buffer-substring-no-properties beg end)) 
      (magit-run-git-async 
       "push" 
       "-v" 
       remote 
       (magit-get-current-branch))))))) 
    (display-buffer (get-buffer magit-process-buffer-name)))) 
相關問題