2014-04-19 2 views
6

Emacs/Magit을 사용하여 로컬 저장소 변경 사항을 원격 웹 사이트로 푸시하고 Github로 한 번에 밀어 넣으십시오.Emacs - Git 저장소를 여러 원격지로 푸시하는 방법

비 -Macit 관련 스레드 (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/* 

이맥스/Magit의 기본 푸시 명령은 한 번에 하나의 밀어 : http://daemianmack.com/magit-cheatsheet.html


미정 사고 :

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

사용할 수있는 명령의 Magit의 쪽지를 참조하십시오 - 이미 구성된 원격 목록을 얻으려면 /usr/local/git/bin/git remote -v을 사용하고, 그런 다음 결과를 사용하여 각각을 푸시합니다. . . 가능하지만 복잡합니다.

;; 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

편집 (2014 년 4 월 23 일) : 추가 비 Magit 솔루션 Github에서 원격와 별도로 추진 -


COMMAND-LINE 레시피

$ 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) 
모든 것을 스테이징하고 모든 커밋 (커밋 메시지를 기본으로 함), 모든 리모컨으로 푸시.

편집 (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))))