Emacs - 如何将Git存储库推送到多个遥控器

时间:2014-04-19 23:59:18

标签: emacs elisp magit

我正在寻求一些帮助,请使用Emacs / Magit将本地存储库更改推送到远程网站并一举推向Github。

我找到了一个非Emacs /非Magit相关的帖子(https://stackoverflow.com/a/3195446/2112489),评论说它是推送到遥控器和Github的最终答案,它有几百个竖起大拇指。我假设(可能不正确)这是我计算机上.gitconfig目录中本地 $HOME文件的良好起点。

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

Emacs / Magit中的基本Push命令一次只能推送一个:

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

请参阅可用命令的Magit备忘单: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    git@github.com:lawlist/my_project.git (fetch)
  origin    git@github.com:lawlist/my_project.git (push)
  remote_website    lawlist@my-website.com:my_project.git (fetch)
  remote_website    lawlist@my-website.com:my_project.git (push)

COMMAND-LINE RECIPE - 分别推送到遥控器和Github:

;; Setup the remote repository and the hook; and the remote destination folder.
ssh lawlist@my-website.com
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 git@github.com:lawlist/my_project.git
/usr/local/git/bin/git remote add remote_website lawlist@my-website.com: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 个答案:

答案 0 :(得分:4)

编辑(2014年4月23日):添加了一个非Magit解决方案来进行全部暂存,提交所有(使用默认提交消息),并推送到所有远程。

编辑(2014年4月24日):所有流程的打印输出现已发送到git-status-buffer,该(propertize "[...]" 'face 'font-lock-warning-face)显示在功能的末尾 - 带有选项用户选择如何处理窗口 - 例如,删除窗口,删除缓冲区和窗口,或什么都不做。使用(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.")) )) ))))))))))))) 添加了一些漂亮的颜色。依赖于预先安装的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)) ))

FIRST DRAFT (2014年4月19日):此功能需要预先安装Magit。 上面的代码需要安装Magit。

  
{{1}}
相关问题