diff --git a/lisp/dabbrev.el b/lisp/dabbrev.el
index 7b6cbb78cef..f9f9fc8bb27 100644
--- a/lisp/dabbrev.el
+++ b/lisp/dabbrev.el
@@ -464,8 +464,21 @@ dabbrev-expand

 See also `dabbrev-abbrev-char-regexp' and \\[dabbrev-completion]."
   (interactive "*P")
-  (let (abbrev record-case-pattern
-	       expansion old direction (orig-point (point)))
+  ;; There are three possible sources of the expansion, which we need to
+  ;; check in a specific order:
+  (let ((buf (cond ((window-minibuffer-p)
+                    ;; If we invoked dabbrev-expand in the minibuffer,
+                    ;; this is the buffer from which we entered the
+                    ;; minibuffer.
+                    (window-buffer (get-mru-window)))
+                   ;; Otherwise, if we found the expansion in another
+                   ;; buffer, use that buffer for further expansions.
+                   (dabbrev--last-buffer-found dabbrev--last-buffer-found)
+                   ;; Otherwise, use the buffer where we invoked
+                   ;; dabbrev-expand.
+                   (t (current-buffer))))
+        abbrev record-case-pattern expansion old direction
+        (orig-point (point)))
     ;; abbrev -- the abbrev to expand
     ;; expansion -- the expansion found (eventually) or nil until then
     ;; old -- the text currently in the buffer
@@ -480,6 +493,7 @@ dabbrev-expand
 			   (point)))))
 	  ;; Find a different expansion for the same abbrev as last time.
 	  (progn
+            (setq dabbrev--last-buffer-found nil)
 	    (setq abbrev dabbrev--last-abbreviation)
 	    (setq old dabbrev--last-expansion)
 	    (setq direction dabbrev--last-direction))
@@ -488,7 +502,14 @@ dabbrev-expand
 	(if (and (eq (preceding-char) ?\s)
 		 (markerp dabbrev--last-abbrev-location)
 		 (marker-position dabbrev--last-abbrev-location)
-		 (= (point) (1+ dabbrev--last-abbrev-location)))
+                 ;; Comparing with point only makes sense in the buffer
+                 ;; where we called dabbrev-exand, but if that differs
+                 ;; from the buffer containing the expansion, we want to
+                 ;; get the next word in the latter buffer, so we skip
+                 ;; the comparison.
+		 (if (eq buf (current-buffer))
+                     (= (point) (1+ dabbrev--last-abbrev-location))
+                   t))
 	    (progn
 	      ;; The "abbrev" to expand is just the space.
 	      (setq abbrev " ")
@@ -549,29 +570,43 @@ dabbrev-expand
                   (if old " further" "") abbrev))
      (t
       (if (not (or (eq dabbrev--last-buffer dabbrev--last-buffer-found)
-		   (minibuffer-window-active-p (selected-window))))
+                   ;; If we are in the minibuffer and an expansion has
+                   ;; been found but dabbrev--last-buffer-found is not
+                   ;; yet set, we need to set it now.
+                   (and dabbrev--last-buffer-found
+		        (minibuffer-window-active-p (selected-window)))))
 	  (progn
             (when (buffer-name dabbrev--last-buffer)
 	      (message "Expansion found in `%s'"
 		       (buffer-name dabbrev--last-buffer)))
 	    (setq dabbrev--last-buffer-found dabbrev--last-buffer))
 	(message nil))
-      (if (and (or (eq (current-buffer) dabbrev--last-buffer)
-		   (null dabbrev--last-buffer)
-                   (buffer-live-p dabbrev--last-buffer))
-	       (numberp dabbrev--last-expansion-location)
-	       (and (> dabbrev--last-expansion-location (point))))
-	  (setq dabbrev--last-expansion-location
-		(copy-marker dabbrev--last-expansion-location)))
+      ;; To get correct further expansions we have to be sure to use the
+      ;; buffer containing the already found expansions.
+      (when dabbrev--last-buffer-found
+        (setq buf dabbrev--last-buffer-found))
+      ;; If the buffer where we called dabbrev-expand differs from the
+      ;; buffer containing the expansion, make sure copy-marker is
+      ;; called in the latter buffer.
+      (with-current-buffer buf
+        (if (and (or (eq (current-buffer) dabbrev--last-buffer)
+		     (null dabbrev--last-buffer)
+                     (buffer-live-p dabbrev--last-buffer))
+	         (numberp dabbrev--last-expansion-location)
+	         (and (> dabbrev--last-expansion-location (point))))
+	    (setq dabbrev--last-expansion-location
+		  (copy-marker dabbrev--last-expansion-location))))
       ;; Success: stick it in and return.
       (setq buffer-undo-list (cons orig-point buffer-undo-list))
       (setq expansion (dabbrev--substitute-expansion old abbrev expansion
                                                      record-case-pattern))

-      ;; Save state for re-expand.
-      (setq dabbrev--last-expansion expansion)
-      (setq dabbrev--last-abbreviation abbrev)
-      (setq dabbrev--last-abbrev-location (point-marker))))))
+      ;; Save state for re-expand (making sure it's the state of the
+      ;; buffer containing the already found expansions).
+      (with-current-buffer buf
+        (setq dabbrev--last-expansion expansion)
+        (setq dabbrev--last-abbreviation abbrev)
+        (setq dabbrev--last-abbrev-location (point-marker)))))))

 ;;----------------------------------------------------------------
 ;; Local functions
diff --git a/test/lisp/dabbrev-tests.el b/test/lisp/dabbrev-tests.el
index c7574403949..987106aa5af 100644
--- a/test/lisp/dabbrev-tests.el
+++ b/test/lisp/dabbrev-tests.el
@@ -25,6 +25,7 @@
 ;;; Code:

 (require 'ert)
+(require 'ert-x)
 (require 'dabbrev)

 (ert-deftest dabbrev-expand-test ()
@@ -68,4 +69,210 @@ dabbrev-completion-test-with-argument
         (execute-kbd-macro (kbd "C-u C-u C-M-/")))
       (should (string= (buffer-string) "abc\na")))))

+(defmacro with-dabbrev-test (&rest body)
+  "Set up an isolated `dabbrev' test environment."
+  (declare (debug (body)))
+  `(ert-with-temp-directory dabbrev-test-home
+     (let* (;; Since we change HOME, clear this to avoid a conflict
+            ;; e.g. if Emacs runs within the user's home directory.
+            (abbreviated-home-dir nil)
+            (process-environment (cons (format "HOME=%s" dabbrev-test-home)
+                                       process-environment))
+            (dabbrev-directory (ert-resource-directory)))
+       (unwind-protect
+           (progn ,@body)
+         ;; Restore pre-test-run state of test files.
+         (dolist (f (directory-files dabbrev-directory))
+           (let ((buf (get-file-buffer f)))
+             (when buf
+               (with-current-buffer buf
+                 (restore-buffer-modified-p nil)
+                 (kill-buffer)))))
+         (dabbrev--reset-global-variables)))))
+
+(ert-deftest dabbrev-expand-test-same-buffer-1 ()
+  "Test expanding a string twice within a single buffer.
+The first expansion should expand the input (a prefix-string) to a
+string in the buffer containing no whitespace character, the second
+expansion, after adding a space to the first expansion, should extend
+the string with the following string in the buffer up to the next
+whitespace character."
+  (with-dabbrev-test
+   (find-file (ert-resource-file "INSTALL_BEGIN"))
+   (goto-char (point-max))
+   (terpri)
+   (execute-kbd-macro (kbd "Ind M-/"))
+   (should (string= (buffer-substring (pos-bol) (pos-eol)) "Indic"))
+   (execute-kbd-macro (kbd "SPC M-/"))
+   (should (string= (buffer-substring (pos-bol) (pos-eol)) "Indic and"))))
+
+(ert-deftest dabbrev-expand-test-same-buffer-2 ()
+  "Test expanding a string plus space twice within a single buffer.
+Each expansion should extend the string with the following string in the
+buffer up to the next whitespace character."
+  (with-dabbrev-test
+   (find-file (ert-resource-file "INSTALL_BEGIN"))
+   (goto-char (point-max))
+   (terpri)
+   (execute-kbd-macro (kbd "Indic SPC M-/"))
+   (should (string= (buffer-substring (pos-bol) (pos-eol)) "Indic and"))
+   (execute-kbd-macro (kbd "SPC M-/"))
+   (should (string= (buffer-substring (pos-bol) (pos-eol)) "Indic and Khmer"))))
+
+(ert-deftest dabbrev-expand-test-same-buffer-3 ()
+  "Test replacing an expansion within a single buffer."
+  (with-dabbrev-test
+   (find-file (ert-resource-file "INSTALL_BEGIN"))
+   (goto-char (point-max))
+   (terpri)
+   (insert-file-contents (ert-resource-file "dabbrev-expand.el"))
+   (goto-char (point-max))
+   (terpri)
+   (execute-kbd-macro (kbd "Ind M-/"))
+   (should (string= (buffer-substring (pos-bol) (pos-eol)) "Indicate"))
+   (kill-whole-line)
+   (execute-kbd-macro (kbd "Ind M-/ M-/"))
+   (should (string= (buffer-substring (pos-bol) (pos-eol)) "Indic"))
+   (execute-kbd-macro (kbd "SPC M-/"))
+   (should (string= (buffer-substring (pos-bol) (pos-eol)) "Indic and"))))
+
+(ert-deftest dabbrev-expand-test-same-buffer-4 ()
+  "Test expanding a string in a narrowed-region."
+  (with-dabbrev-test
+   (let (disabled-command-function) ; Enable narrow-to-region.
+     (find-file (ert-resource-file "INSTALL_BEGIN"))
+     (goto-char (point-min))
+     (execute-kbd-macro (kbd "C-s Ind M-a C-SPC M-} C-x n n"))
+     (goto-char (point-max))
+     (terpri)
+     (execute-kbd-macro (kbd "Ind M-/"))
+     (should (string= (buffer-substring (pos-bol) (pos-eol)) "Indic"))
+     (execute-kbd-macro (kbd "SPC M-/"))
+     (should (string= (buffer-substring (pos-bol) (pos-eol)) "Indic and")))))
+
+(ert-deftest dabbrev-expand-test-other-buffer-1 ()
+  "Test expanding a prefix string to a string from another buffer."
+  (with-dabbrev-test
+   (find-file (ert-resource-file "INSTALL_BEGIN"))
+   (switch-to-buffer (get-buffer-create "a" t))
+   (execute-kbd-macro (kbd "Ind M-/"))
+   (should (string= (buffer-string) "Indic"))
+   (execute-kbd-macro (kbd "SPC M-/"))
+   (should (string= (buffer-string) "Indic and"))
+   (kill-buffer "a")))
+
+(ert-deftest dabbrev-expand-test-other-buffer-2 ()
+  "Test expanding a string + space to a string from another buffer."
+  (with-dabbrev-test
+   (find-file (ert-resource-file "INSTALL_BEGIN"))
+   (switch-to-buffer (get-buffer-create "a" t))
+   (execute-kbd-macro (kbd "Indic SPC M-/"))
+   (should (string= (buffer-string) "Indic and"))
+   (execute-kbd-macro (kbd "SPC M-/"))
+   (should (string= (buffer-string) "Indic and Khmer"))
+   (kill-buffer "a")))
+
+(ert-deftest dabbrev-expand-test-other-buffer-3 ()
+  "Test replacing an expansion with three different buffers.
+A prefix string in a buffer should find the first expansion in a
+different buffer and then find a replacement expansion is yet another
+buffer."
+  (with-dabbrev-test
+   (find-file (ert-resource-file "INSTALL_BEGIN"))
+   (find-file (ert-resource-file "dabbrev-expand.el"))
+   (switch-to-buffer (get-buffer-create "a" t))
+   (emacs-lisp-mode)
+   (execute-kbd-macro (kbd "Ind M-/"))
+   (should (string= (buffer-string) "Indicate"))
+   (erase-buffer)
+   (execute-kbd-macro (kbd "Ind M-/ M-/"))
+   (should (string= (buffer-string) "Indic"))
+   (execute-kbd-macro (kbd "SPC M-/"))
+   (should (string= (buffer-string) "Indic and"))
+   (kill-buffer "a")))
+
+(ert-deftest dabbrev-expand-test-other-buffer-4 ()
+  "Test expanding a string using another narrowed buffer."
+  (with-dabbrev-test
+   (let (disabled-command-function) ; Enable narrow-to-region.
+     (find-file (ert-resource-file "INSTALL_BEGIN"))
+     (goto-char (point-min))
+     (execute-kbd-macro (kbd "C-s Ind M-a C-SPC M-} C-x n n"))
+     (switch-to-buffer (get-buffer-create "a" t))
+     (execute-kbd-macro (kbd "Ind M-/"))
+     (should (string= (buffer-string) "Indic"))
+     (execute-kbd-macro (kbd "SPC M-/"))
+     (should (string= (buffer-string) "Indic and"))
+     (kill-buffer "a"))))
+
+(ert-deftest dabbrev-expand-test-minibuffer-1 ()
+  "Test expanding a prefix string twice in the minibuffer.
+Both expansions should come from the buffer from which the minibuffer
+was entered."
+  (with-dabbrev-test
+   (find-file (ert-resource-file "INSTALL_BEGIN"))
+   (with-selected-window (minibuffer-window)
+     (insert "Ind")
+     (dabbrev-expand nil)
+     (should (string= (minibuffer-contents) "Indic"))
+     (insert " ")
+     (dabbrev-expand nil)
+     (should (string= (minibuffer-contents) "Indic and"))
+     (delete-minibuffer-contents))))
+
+(ert-deftest dabbrev-expand-test-minibuffer-2 ()
+  "Test expanding a string + space in the minibuffer.
+The expansions should come from the buffer from which the minibuffer was
+entered."
+  (with-dabbrev-test
+   (find-file (ert-resource-file "INSTALL_BEGIN"))
+   (with-selected-window (minibuffer-window)
+     (insert "Indic ")
+     (dabbrev-expand nil)
+     (should (string= (minibuffer-contents) "Indic and"))
+     (insert " ")
+     (dabbrev-expand nil)
+     (should (string= (buffer-string) "Indic and Khmer"))
+     (delete-minibuffer-contents))))
+
+;; FIXME: Why is dabbrev--reset-global-variables needed here?
+(ert-deftest dabbrev-expand-test-minibuffer-3 ()
+  "Test replacing an expansion in the minibuffer using two buffers.
+The first expansion should befound in the buffer from which the
+minibuffer was entered, the replacement should found in another buffer."
+  (with-dabbrev-test
+   (find-file (ert-resource-file "INSTALL_BEGIN"))
+   (find-file (ert-resource-file "dabbrev-expand.el"))
+   (with-selected-window (minibuffer-window)
+     (insert "Ind")
+     (dabbrev-expand nil)
+     (should (string= (minibuffer-contents) "Indicate"))
+     (kill-whole-line)
+     (dabbrev--reset-global-variables)
+     (insert "Ind")
+     (dabbrev-expand nil)
+     (dabbrev-expand nil)
+     (should (string= (minibuffer-contents) "Indic"))
+     (dabbrev--reset-global-variables)
+     (insert " ")
+     (dabbrev-expand nil)
+     (should (string= (minibuffer-contents) "Indic and"))
+     (delete-minibuffer-contents))))
+
+(ert-deftest dabbrev-expand-test-minibuffer-4 ()
+  "Test expansion in the minibuffer using another narrowed buffer."
+  (with-dabbrev-test
+   (let (disabled-command-function) ; Enable narrow-to-region.
+     (find-file (ert-resource-file "INSTALL_BEGIN"))
+     (goto-char (point-min))
+     (execute-kbd-macro (kbd "C-s Ind M-a C-SPC M-} C-x n n")))
+   (with-selected-window (minibuffer-window)
+     (insert "Ind")
+     (dabbrev-expand nil)
+     (should (string= (minibuffer-contents) "Indic"))
+     (insert " ")
+     (dabbrev-expand nil)
+     (should (string= (minibuffer-contents) "Indic and"))
+     (delete-minibuffer-contents))))
+
 ;;; dabbrev-tests.el ends here
